(function () {
/**
 * @license almond 0.3.3 Copyright jQuery Foundation and other contributors.
 * Released under MIT license, http://github.com/requirejs/almond/LICENSE
 */
//Going sloppy to avoid 'use strict' string cost, but strict practices should
//be followed.
/*global setTimeout: false */

var requirejs, require, define;
(function (undef) {
    var main, req, makeMap, handlers,
        defined = {},
        waiting = {},
        config = {},
        defining = {},
        hasOwn = Object.prototype.hasOwnProperty,
        aps = [].slice,
        jsSuffixRegExp = /\.js$/;

    function hasProp(obj, prop) {
        return hasOwn.call(obj, prop);
    }

    /**
     * Given a relative module name, like ./something, normalize it to
     * a real name that can be mapped to a path.
     * @param {String} name the relative name
     * @param {String} baseName a real name that the name arg is relative
     * to.
     * @returns {String} normalized name
     */
    function normalize(name, baseName) {
        var nameParts, nameSegment, mapValue, foundMap, lastIndex,
            foundI, foundStarMap, starI, i, j, part, normalizedBaseParts,
            baseParts = baseName && baseName.split("/"),
            map = config.map,
            starMap = (map && map['*']) || {};

        //Adjust any relative paths.
        if (name) {
            name = name.split('/');
            lastIndex = name.length - 1;

            // If wanting node ID compatibility, strip .js from end
            // of IDs. Have to do this here, and not in nameToUrl
            // because node allows either .js or non .js to map
            // to same file.
            if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
                name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
            }

            // Starts with a '.' so need the baseName
            if (name[0].charAt(0) === '.' && baseParts) {
                //Convert baseName to array, and lop off the last part,
                //so that . matches that 'directory' and not name of the baseName's
                //module. For instance, baseName of 'one/two/three', maps to
                //'one/two/three.js', but we want the directory, 'one/two' for
                //this normalization.
                normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);
                name = normalizedBaseParts.concat(name);
            }

            //start trimDots
            for (i = 0; i < name.length; i++) {
                part = name[i];
                if (part === '.') {
                    name.splice(i, 1);
                    i -= 1;
                } else if (part === '..') {
                    // If at the start, or previous value is still ..,
                    // keep them so that when converted to a path it may
                    // still work when converted to a path, even though
                    // as an ID it is less than ideal. In larger point
                    // releases, may be better to just kick out an error.
                    if (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') {
                        continue;
                    } else if (i > 0) {
                        name.splice(i - 1, 2);
                        i -= 2;
                    }
                }
            }
            //end trimDots

            name = name.join('/');
        }

        //Apply map config if available.
        if ((baseParts || starMap) && map) {
            nameParts = name.split('/');

            for (i = nameParts.length; i > 0; i -= 1) {
                nameSegment = nameParts.slice(0, i).join("/");

                if (baseParts) {
                    //Find the longest baseName segment match in the config.
                    //So, do joins on the biggest to smallest lengths of baseParts.
                    for (j = baseParts.length; j > 0; j -= 1) {
                        mapValue = map[baseParts.slice(0, j).join('/')];

                        //baseName segment has  config, find if it has one for
                        //this name.
                        if (mapValue) {
                            mapValue = mapValue[nameSegment];
                            if (mapValue) {
                                //Match, update name to the new value.
                                foundMap = mapValue;
                                foundI = i;
                                break;
                            }
                        }
                    }
                }

                if (foundMap) {
                    break;
                }

                //Check for a star map match, but just hold on to it,
                //if there is a shorter segment match later in a matching
                //config, then favor over this star map.
                if (!foundStarMap && starMap && starMap[nameSegment]) {
                    foundStarMap = starMap[nameSegment];
                    starI = i;
                }
            }

            if (!foundMap && foundStarMap) {
                foundMap = foundStarMap;
                foundI = starI;
            }

            if (foundMap) {
                nameParts.splice(0, foundI, foundMap);
                name = nameParts.join('/');
            }
        }

        return name;
    }

    function makeRequire(relName, forceSync) {
        return function () {
            //A version of a require function that passes a moduleName
            //value for items that may need to
            //look up paths relative to the moduleName
            var args = aps.call(arguments, 0);

            //If first arg is not require('string'), and there is only
            //one arg, it is the array form without a callback. Insert
            //a null so that the following concat is correct.
            if (typeof args[0] !== 'string' && args.length === 1) {
                args.push(null);
            }
            return req.apply(undef, args.concat([relName, forceSync]));
        };
    }

    function makeNormalize(relName) {
        return function (name) {
            return normalize(name, relName);
        };
    }

    function makeLoad(depName) {
        return function (value) {
            defined[depName] = value;
        };
    }

    function callDep(name) {
        if (hasProp(waiting, name)) {
            var args = waiting[name];
            delete waiting[name];
            defining[name] = true;
            main.apply(undef, args);
        }

        if (!hasProp(defined, name) && !hasProp(defining, name)) {
            throw new Error('No ' + name);
        }
        return defined[name];
    }

    //Turns a plugin!resource to [plugin, resource]
    //with the plugin being undefined if the name
    //did not have a plugin prefix.
    function splitPrefix(name) {
        var prefix,
            index = name ? name.indexOf('!') : -1;
        if (index > -1) {
            prefix = name.substring(0, index);
            name = name.substring(index + 1, name.length);
        }
        return [prefix, name];
    }

    //Creates a parts array for a relName where first part is plugin ID,
    //second part is resource ID. Assumes relName has already been normalized.
    function makeRelParts(relName) {
        return relName ? splitPrefix(relName) : [];
    }

    /**
     * Makes a name map, normalizing the name, and using a plugin
     * for normalization if necessary. Grabs a ref to plugin
     * too, as an optimization.
     */
    makeMap = function (name, relParts) {
        var plugin,
            parts = splitPrefix(name),
            prefix = parts[0],
            relResourceName = relParts[1];

        name = parts[1];

        if (prefix) {
            prefix = normalize(prefix, relResourceName);
            plugin = callDep(prefix);
        }

        //Normalize according
        if (prefix) {
            if (plugin && plugin.normalize) {
                name = plugin.normalize(name, makeNormalize(relResourceName));
            } else {
                name = normalize(name, relResourceName);
            }
        } else {
            name = normalize(name, relResourceName);
            parts = splitPrefix(name);
            prefix = parts[0];
            name = parts[1];
            if (prefix) {
                plugin = callDep(prefix);
            }
        }

        //Using ridiculous property names for space reasons
        return {
            f: prefix ? prefix + '!' + name : name, //fullName
            n: name,
            pr: prefix,
            p: plugin
        };
    };

    function makeConfig(name) {
        return function () {
            return (config && config.config && config.config[name]) || {};
        };
    }

    handlers = {
        require: function (name) {
            return makeRequire(name);
        },
        exports: function (name) {
            var e = defined[name];
            if (typeof e !== 'undefined') {
                return e;
            } else {
                return (defined[name] = {});
            }
        },
        module: function (name) {
            return {
                id: name,
                uri: '',
                exports: defined[name],
                config: makeConfig(name)
            };
        }
    };

    main = function (name, deps, callback, relName) {
        var cjsModule, depName, ret, map, i, relParts,
            args = [],
            callbackType = typeof callback,
            usingExports;

        //Use name if no relName
        relName = relName || name;
        relParts = makeRelParts(relName);

        //Call the callback to define the module, if necessary.
        if (callbackType === 'undefined' || callbackType === 'function') {
            //Pull out the defined dependencies and pass the ordered
            //values to the callback.
            //Default to [require, exports, module] if no deps
            deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
            for (i = 0; i < deps.length; i += 1) {
                map = makeMap(deps[i], relParts);
                depName = map.f;

                //Fast path CommonJS standard dependencies.
                if (depName === "require") {
                    args[i] = handlers.require(name);
                } else if (depName === "exports") {
                    //CommonJS module spec 1.1
                    args[i] = handlers.exports(name);
                    usingExports = true;
                } else if (depName === "module") {
                    //CommonJS module spec 1.1
                    cjsModule = args[i] = handlers.module(name);
                } else if (hasProp(defined, depName) ||
                           hasProp(waiting, depName) ||
                           hasProp(defining, depName)) {
                    args[i] = callDep(depName);
                } else if (map.p) {
                    map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});
                    args[i] = defined[depName];
                } else {
                    throw new Error(name + ' missing ' + depName);
                }
            }

            ret = callback ? callback.apply(defined[name], args) : undefined;

            if (name) {
                //If setting exports via "module" is in play,
                //favor that over return value and exports. After that,
                //favor a non-undefined return value over exports use.
                if (cjsModule && cjsModule.exports !== undef &&
                        cjsModule.exports !== defined[name]) {
                    defined[name] = cjsModule.exports;
                } else if (ret !== undef || !usingExports) {
                    //Use the return value from the function.
                    defined[name] = ret;
                }
            }
        } else if (name) {
            //May just be an object definition for the module. Only
            //worry about defining if have a module name.
            defined[name] = callback;
        }
    };

    requirejs = require = req = function (deps, callback, relName, forceSync, alt) {
        if (typeof deps === "string") {
            if (handlers[deps]) {
                //callback in this case is really relName
                return handlers[deps](callback);
            }
            //Just return the module wanted. In this scenario, the
            //deps arg is the module name, and second arg (if passed)
            //is just the relName.
            //Normalize module name, if it contains . or ..
            return callDep(makeMap(deps, makeRelParts(callback)).f);
        } else if (!deps.splice) {
            //deps is a config object, not an array.
            config = deps;
            if (config.deps) {
                req(config.deps, config.callback);
            }
            if (!callback) {
                return;
            }

            if (callback.splice) {
                //callback is an array, which means it is a dependency list.
                //Adjust args if there are dependencies
                deps = callback;
                callback = relName;
                relName = null;
            } else {
                deps = undef;
            }
        }

        //Support require(['a'])
        callback = callback || function () {};

        //If relName is a function, it is an errback handler,
        //so remove it.
        if (typeof relName === 'function') {
            relName = forceSync;
            forceSync = alt;
        }

        //Simulate async callback;
        if (forceSync) {
            main(undef, deps, callback, relName);
        } else {
            //Using a non-zero value because of concern for what old browsers
            //do, and latest browsers "upgrade" to 4 if lower value is used:
            //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:
            //If want a value immediately, use require('id') instead -- something
            //that works in almond on the global level, but not guaranteed and
            //unlikely to work in other AMD implementations.
            setTimeout(function () {
                main(undef, deps, callback, relName);
            }, 4);
        }

        return req;
    };

    /**
     * Just drops the config on the floor, but returns req in case
     * the config return value is used.
     */
    req.config = function (cfg) {
        return req(cfg);
    };

    /**
     * Expose module registry for debugging and tooling
     */
    requirejs._defined = defined;

    define = function (name, deps, callback) {
        if (typeof name !== 'string') {
            throw new Error('See almond README: incorrect module build, no module name');
        }

        //This module may not have dependencies
        if (!deps.splice) {
            //deps is not an array, so probably means
            //an object literal or factory function for
            //the value. Adjust args.
            callback = deps;
            deps = [];
        }

        if (!hasProp(defined, name) && !hasProp(waiting, name)) {
            waiting[name] = [name, deps, callback];
        }
    };

    define.amd = {
        jQuery: true
    };
}());

define('SGWorld/Navigate/flyTo',[], function () {
    'use strict';

    /**
     *
     * 飞向对象。
     *
     * @alias flyTo
     * @constructor
     *
     */
    function _() {
        
    }

    _.prototype.flyTo = function () {
       
    }


    return _;
});

define('SGWorld/Navigate/Navigate',[
    "./flyTo"
], function (
             flyTo
) {
    'use strict';

    /**
     *
     * 导航模块。
     *
     * @alias Navigate
     * @constructor
     *
     */


    function Navigate(viewer, cesium, tree) {
        this._flyTo = new flyTo();
    };
    /**
     * 这个方法用于视点飞到一个对象
     *
     */
    Navigate.prototype.flyTo = function () {
        
    }
    
    return Navigate;
});
/**
 *
 *      实现功能：工具。
 *
 *      创建人员：张丹钊
 *
 *      创建日期：2020-03-15
 *
 *      参与人员：张丹钊
 *
 *      最后修改人员：张丹钊
 *
 *      最后修改时间：2020-03-15
 *
 * */
define('SGWorld/Core/Core',[], function () {
    'use strict';

    function _() {
        this.helpTooltip = undefined;
    }

    //数据数组去重
    _.prototype.unique = function (arr) {
        var newArr = []
        for (var i = 0; i < arr.length; i++) {
            if (newArr.indexOf(arr[i]) === -1) {
                newArr.push(arr[i])
            }
        }
        return newArr
    }

    //数据对比获取属性
    _.prototype.extend = function (o, n, override) {
        for (var key in n) {
            if (n.hasOwnProperty(key) && (!o.hasOwnProperty(key) || override)) {
                o[key] = n[key];
            }
        }
        //this.extendgl(o);
        return o;
    }

    //默认值
    _.prototype.defaultValue = function (a, b) {
        if (a !== undefined && a !== null) {
            return a;
        }
        return b;
    }

    //数据对比获取属性
    _.prototype.addEPSG = function (proj) {
        let projection = ol.proj.get(proj);
        if (!projection) {
            if (proj === "EPSG:4490") {
                proj4.defs("EPSG:4490", "+proj=longlat +ellps=GRS80 +no_defs");
                ol.proj.proj4.register(proj4);
                projection = ol.proj.get('EPSG:4490');
                projection.setExtent([-180, -90, 180, 90]);
                projection.matrixIds = ['EPSG:4490:0', 'EPSG:4490:1', 'EPSG:4490:2', 'EPSG:4490:3', 'EPSG:4490:4', 'EPSG:4490:5', 'EPSG:4490:6', 'EPSG:4490:7', 'EPSG:4490:8', 'EPSG:4490:9', 'EPSG:4490:10', 'EPSG:4490:11', 'EPSG:4490:12', 'EPSG:4490:13', 'EPSG:4490:14', 'EPSG:4490:15', 'EPSG:4490:16', 'EPSG:4490:17', 'EPSG:4490:18', 'EPSG:4490:19', 'EPSG:4490:20', 'EPSG:4490:21'];
                projection.resolutions = [0.703125, 0.3515625, 0.17578125, 0.087890625, 0.0439453125, 0.02197265625, 0.010986328125, 0.0054931640625, 0.00274658203125, 0.001373291015625, 6.866455078125E-4, 3.433227539062E-4, 1.716613769531E-4, 8.58306884766E-5, 4.29153442383E-5, 2.14576721191E-5, 1.07288360596E-5, 5.3644180298E-6, 2.6822090149E-6, 1.3411045074E-6, 6.705522537E-7, 3.352761269E-7];
                projection.units = 'degrees';
                projection.axisOrientation = 'neu';
            }
        }
    }

    //添加tooltip样式
    _.prototype.addTooltipStyle = function () {
        if (!this.TooltipStyle) {
            var style = document.createElement('style');
            style.innerHTML = '.ol-tooltip-help {' +
                'position: relative;' +
                'background: rgba(0, 0, 0, 0.5);' +
                'border-radius: 4px;' +
                'color: white;' +
                'padding: 4px 8px;' +
                'opacity: 1;' +
                'white-space: nowrap;' +
                'font-size: 12px;' +
                '}' +

                '.ol-tooltip-result {' +
                'position: relative;' +
                'background: rgba(0, 0, 0, 0.5);' +
                'border-radius: 4px;' +
                'color: white;' +
                'padding: 4px 8px;' +
                'opacity: 1;' +
                'font-weight: bold;' +
                'white-space: nowrap;' +
                'font-size: 12px;' +
                '}' +

                '.ol-tooltip-result-static {' +
                'color: black;' +
                'background-color: #ffcc33;' +
                'border: 1px solid white;' +
                '}' +

                '.ol-tooltip-result:before,' +
                '.ol-tooltip-result-static:before {' +
                'border-top: 6px solid rgba(0, 0, 0, 0.5);' +
                'border-right: 6px solid transparent;' +
                'border-left: 6px solid transparent;' +
                'content: "";' +
                'position: absolute;' +
                'bottom: -6px;' +
                'margin-left: -7px;' +
                'left: 50%;' +
                '}' +
                '.ol-tooltip-result-static:before {' +
                'border-top-color: #ffcc33;' +
                '}';
            document.head.appendChild(style);
            this.TooltipStyle = true;
        };
    }

    /**
     * 创建helpToolTip
     */
    _.prototype.createHelpTooltip = function (map) {
        this.addTooltipStyle();
        var helpTooltipElement = document.getElementById('ol-tooltip-help');
        if (!helpTooltipElement) {
            helpTooltipElement = document.createElement('div');
            helpTooltipElement.className = 'ol-tooltip-help';
            helpTooltipElement.id = 'ol-tooltip-help';

            this.helpTooltip = new ol.Overlay({
                element: helpTooltipElement,
                offset: [15, 0],
                positioning: 'center-left'
            });
            this.helpTooltip.element.style.pointerEvents = 'none';
            map.addOverlay(this.helpTooltip);
        }
        var _this = this;
        return {
            isShow: false,
            helpTooltip: _this.helpTooltip,
            helpTooltipElement: helpTooltipElement,
            show: function (visiable) {
                this.isShow = visiable;
                helpTooltipElement.style.display = visiable ? 'block' : 'none';
            },
            showAt: function (msg, position) {
                this.show(true);
                helpTooltipElement.innerHTML = msg;
                _this.helpTooltip.setPosition(position);
            }
        }
    }

    /**
     * 创建resultToolTip
     */
    _.prototype.createResultTooltip = function (map, isStatic, option) {
        this.addTooltipStyle();
        var resultTooltipElement = document.createElement('div');
        resultTooltipElement.className = 'ol-tooltip-result';
        !option && (option = {});
        var resultTooltip = new ol.Overlay({
            element: resultTooltipElement,
            offset: this.defaultValue(option.offset, [0, -15]),
            positioning: this.defaultValue(option.position, 'bottom-center')
        });
        resultTooltip.element.style.pointerEvents = 'none';
        map.addOverlay(resultTooltip);

        //状态
        isStatic && State(isStatic);

        function State(_isStatic) {
            if (_isStatic) {
                resultTooltipElement.className = 'ol-tooltip-result ol-tooltip-result-static';
            } else {
                resultTooltipElement.className = 'ol-tooltip-result';
            }
        }

        return {
            isShow: true,
            position: undefined,
            resultTooltip: resultTooltip,
            resultTooltipElement: resultTooltipElement,
            show: function (visiable) {
                this.isShow = visiable;
                resultTooltipElement.style.display = visiable ? 'block' : 'none';
            },
            showAt: function (msg, position) {
                this.show(true);
                this.position = position;
                resultTooltipElement.innerHTML = msg;
                resultTooltip.setPosition(position);
            },
            static: function (_isStatic) {
                State(_isStatic);
            },
            setPosition: function (position) {
                this.position = position;
                resultTooltip.setPosition(position);
            },
            remove: function () {
                map.removeOverlay(resultTooltip);
            }
        }
    }

    /**
     * 缩放到矢量位置
     */
    _.prototype.zoomToFeature = function (feature, map) {
        let Extent = feature.getGeometry().getExtent();
        //方式1（可控制视野大小）
        var r = map.getView().getResolutionForExtent(Extent, map.getSize());
        map.getView().setResolution(r + 0.5);
        map.getView().setCenter(ol.extent.getCenter(Extent));

        //方式2（矢量充满全屏）
        //map.getView().fit(Extent, map.getSize());
    }

    return _;
});
/**
 *
 *      实现功能：创建颜色。
 *      
 *      创建人员：薛鹏
 *      
 *      创建日期：2019-03-13
 *      
 *      参与人员：薛鹏
 *      
 *      最后修改人员：薛鹏
 * 
 *      最后修改时间：2019-03-13
 * 
 * */
define('SGWorld/Creator/Color',['../Core/Core'], function (Core) {
    'use strict';
    /**
    *
    * 这个方法用于创建颜色。
    *
    * @alias createColor 
    * @constructor
    *
    */
    function _() {
        this._core = new Core();
    }

    /**
    * 这个方法用于创建颜色
    *@param {number} [red] 红。
    * @param {number} [green] 绿。
    * @param {number} [blue] 蓝。
    * @param {number} [alphae] alphea。
    * @returns {Promise.<Object>} 返回一个Openlayer的颜色对象。
    */
    _.prototype.createColor = function () {
    
    }

    return _;
});
/**
 *
 *      实现功能：创建图层。
 *      
 *      创建人员：张丹钊
 *
 *      创建日期：2020-03-17
 *
 *      参与人员：张丹钊
 *
 *      最后修改人员：张丹钊
 *
 *      最后修改时间：2020-03-17
 *
 * */
define('SGWorld/Creator/Layer',['../Core/Core'], function (Core) {
    'use strict';
    /**
    *
    * 这个方法用于创建图层。
    *
    * @alias addLayer 
    * @constructor
    *
    */
    function _(map) {
        this._map = map;
        this._core = new Core();
    }

    /**
    * 这个方法用于添加切片图层
    *@param {String} [name] 名称
    *@param {String} [urlOrSource] url或source。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    _.prototype.addTileLayer = function (name, urlOrSource, option, callback) {
        let layerOption;
        !option && (option = {});
        if (typeof urlOrSource === 'string') {
            layerOption = {
                source: new ol.source.XYZ({
                    url: urlOrSource
                })
            }
        } else if (typeof urlOrSource === 'object') {
            layerOption = {
                source: urlOrSource
            }
        } else {
            layerOption = {};
        }

        layerOption = this._core.extend(layerOption, option, true);
        name && (layerOption.className = name);
        let layer = new ol.layer.Tile(layerOption);

        this._map.addLayer(layer);

        return layer;
    }

    /**
    * 这个方法用于添加影像图层
    *@param {String} [name] 名称
    *@param {String} [urlOrSource] url或source。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    _.prototype.addImageLayer = function (name, urlOrSource, option, callback) {
        let layerOption;
        !option && (option = {});
        if (typeof urlOrSource === 'string') {
            layerOption = {
                source: new ol.source.ImageStatic({
                    url: urlOrSource,
                    projection: option.projection || 'EPSG:4326',
                    imageExtent: option.imageExtent || [-180, -90, 180, 90]
                })
            }
        } else if (typeof urlOrSource === 'object') {
            layerOption = {
                source: urlOrSource
            }
        } else {
            layerOption = {};
        }

        layerOption = this._core.extend(layerOption, option, true);
        name && (layerOption.className = name);
        let layer = new ol.layer.Image(layerOption);

        this._map.addLayer(layer);

        return layer;
    }

    /**
    * 这个方法用于添加ArcGISRest切片服务
    *@param {String} [name] 名称
    *@param {String} [urlOrSource] url或source。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    _.prototype.TileArcGISRest = function (name, urlOrSource, option, callback) {
        let layerOption;
        !option && (option = {});
        if (typeof urlOrSource === 'string') {
            layerOption = {
                source: new ol.source.TileArcGISRest({
                    url: urlOrSource
                })
            }
        } else if (typeof urlOrSource === 'object') {
            layerOption = {
                source: urlOrSource
            }
        } else {
            layerOption = {};
        }

        layerOption = this._core.extend(layerOption, option, true);
        name && (layerOption.className = name);
        let layer = new ol.layer.Tile(layerOption);

        this._map.addLayer(layer);

        return layer;
    }

    /**
    * 这个方法用于添加ArcGISRest影像服务
    *@param {String} [name] 名称
    *@param {String} [urlOrSource] url或source。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    _.prototype.ImageArcGISRest = function (name, urlOrSource, option, callback) {
        let layerOption;
        !option && (option = {});
        if (typeof urlOrSource === 'string') {
            layerOption = {
                source: new ol.source.ImageArcGISRest({
                    ratio: option.ratio || 1,
                    params: option.params || {},
                    url: urlOrSource
                })
            }
        } else if (typeof urlOrSource === 'object') {
            layerOption = {
                source: urlOrSource
            }
        } else {
            layerOption = {};
        }

        layerOption = this._core.extend(layerOption, option, true);
        name && (layerOption.className = name);
        let layer = new ol.layer.Image(layerOption);

        this._map.addLayer(layer);

        return layer;
    }

    /**
    * 这个方法用于添加FeatureService服务
    *@param {String} [name] 名称
    *@param {String} [urlOrSource] url或source。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    _.prototype.FeatureService = function (name, urlOrSource, option, callback) {
        let layerOption;
        !option && (option = {});

        var esrijsonFormat = new ol.format.EsriJSON();
        if (typeof urlOrSource === 'string') {
            !option.layer && (option.layer = '0');
            !option.wkid && (option.wkid = '102100');
            layerOption = {
                source: new ol.source.Vector({
                    loader: function (extent, resolution, projection) {
                        var url = urlOrSource + option.layer + '/query/?f=json&' +
                            'returnGeometry=true&spatialRel=esriSpatialRelIntersects&geometry=' +
                            encodeURIComponent('{"xmin":' + extent[0] + ',"ymin":' +
                                extent[1] + ',"xmax":' + extent[2] + ',"ymax":' + extent[3] +
                                ',"spatialReference":{"wkid":' + option.wkid + '}}') +
                            '&geometryType=esriGeometryEnvelope&inSR=' + option.wkid + '&outFields=*' +
                            '&outSR=' + option.wkid;
                        $.ajax({
                            url: url, dataType: 'jsonp', success: function (response) {
                                if (response.error) {
                                    alert(response.error.message + '\n' +
                                        response.error.details.join('\n'));
                                } else {
                                    // dataProjection will be read from document
                                    var features = esrijsonFormat.readFeatures(response, {
                                        featureProjection: projection
                                    });
                                    if (features.length > 0) {
                                        layerOption.source.addFeatures(features);
                                    }
                                }
                            }
                        });
                    },
                    strategy: ol.loadingstrategy.tile(ol.tilegrid.createXYZ({
                        tileSize: this._core.defaultValue(option.tileSize, 512)
                    }))
                })
            }
        } else if (typeof urlOrSource === 'object') {
            layerOption = {
                source: urlOrSource
            }
        } else {
            layerOption = {};
        }

        layerOption = this._core.extend(layerOption, option, true);

        if (!layerOption.style) {
            let style = {};
            if (layerOption.fillColor) {
                style.fill = new ol.style.Fill({
                    color: layerOption.fillColor
                });
            }
            if (layerOption.lineColor || layerOption.width) {
                style.stroke = new ol.style.Stroke({
                    color: this._core.defaultValue(layerOption.lineColor, 'rgba(0, 0, 255, 1.0)'),
                    width: this._core.defaultValue(layerOption.width, 2)
                });
            }
            if (layerOption.textColor || layerOption.textScale) {
                style.text = new ol.style.Text({
                    fill: this._core.defaultValue(layerOption.textColor, '#333'),
                    scale: this._core.defaultValue(layerOption.textScale, 1)
                });
            }
            if (style.fill || style.stroke || style.text) {
                layerOption.style = new ol.style.Style(style);
            }else{
                layerOption.style = new ol.style.Style({
                    fill: new ol.style.Fill({
                        color: 'rgba(255, 0, 0, 255)'
                    }),
                    stroke: new ol.style.Stroke({
                        color: 'rgba(0, 255, 0, 255)',
                        width: 0.5
                    })
                });
            }
        }
        name && (layerOption.className = name);
        let layer = new ol.layer.Vector(layerOption);

        this._map.addLayer(layer);

        return layer;
    }
    return _;
});
/**
 *
 *      实现功能：创建点。
 *      
 *      创建人员：薛鹏
 *
 *      创建日期：2020-03-17
 *
 *      参与人员：薛鹏、张丹钊
 *
 *      最后修改人员：薛鹏
 *
 *      最后修改时间：2020-03-17
 *
 * */
define('SGWorld/Creator/Point',['../Core/Core'], function (Core) {
    'use strict';
    /**
    *
    * 这个方法用于创建点。
    *
    * @alias addLayer 
    * @constructor
    *
    */
    function _(map) {
        this._map = map;
        this._core = new Core();
    }

    /**
    * 这个方法用于添加点对象
    * @param {Object} [option] 图层参数。
    * 
    */
    _.prototype.createPoint = function (option) {
        !option && (option = {});

        let layerOption = {
            source: new ol.source.Vector()
        }

        layerOption = this._core.extend(layerOption, option, true);

        if (!layerOption.style) {
            let style = {};
            if (layerOption.text) {
                style.text = new ol.style.Text({
                    text: layerOption.text,
                    font: this._core.defaultValue(layerOption.font, undefined),
                    fill: new ol.style.Fill({
                        color: this._core.defaultValue(layerOption.color, '#fff')
                    }),
                    stroke: new ol.style.Stroke({
                        color: this._core.defaultValue(layerOption.outlineColor, '#333'),
                        width: 1
                    }),
                    scale: this._core.defaultValue(layerOption.scale, 1)
                });
            }
            if (layerOption.image) {
                style.image = new ol.style.Icon({
                    src: layerOption.image,
                    scale: this._core.defaultValue(layerOption.scale, 1),
                    anchor: this._core.defaultValue(layerOption.anchor, undefined)
                });
            }
            if (style.text || style.image) {
                layerOption.style = new ol.style.Style(style);
            } else {
                layerOption.style = new ol.style.Style({
                    image: new ol.style.Circle({
                        radius: this._core.defaultValue(layerOption.radius, 7),
                        fill: new ol.style.Fill({
                            color: this._core.defaultValue(layerOption.color, '#ffcc33')
                        })
                    })
                });
            }
        }
        this.vector = new ol.layer.Vector(layerOption);
        this._map.addLayer(this.vector);

        this.draw = new ol.interaction.Draw({
            source: layerOption.source,
            type: "Point"
        });
        this._map.addInteraction(this.draw);

        return this;
    }

    /**
    * 这个方法用于添加div点对象
    * @param {Array} [position] 位置
    * @param {Object} [option] 点参数。
    * 
    */
    _.prototype.addDivPoint = function (position, option) {
        !option && (option = {});
        let Element = document.createElement('div');
        Element.className = 'ol-div-point';

        let item = new ol.Overlay({
            element: Element,
            offset: this._core.defaultValue(option.offset, [0, 0]),
            positioning: this._core.defaultValue(option.positioning, 'bottom-left')
        });
        item.element.style.pointerEvents = 'none';
        let divPointHtml;
        if (option.description) {
            divPointHtml = '<div style="width: 200px; height: 157px; background: url(' + this._core.defaultValue(option.url, 'http://36.7.136.132:1988/sdkdemo/src/static/image/divpoint.png') + ');">\n' +
                '                   <div class="divpoint-title" style="position: absolute;top: 22px;left: 70px;font-size: 14px;text-align: left;color: rgba(255,255,255,1);text-shadow: 0 0 9px rgba(0,0,0,.75)">' + this._core.defaultValue(option.name, 'SmartEarth') + '</div>\n' +
                '                   <div class="divpoint-content" style="position: absolute;font-size: 14px;top: 50px;left: 50px;width: 140px;text-align: left;color: rgba(255,255,255,1);">' + option.description + '</div> \n' +
                '           </div>';
        } else {
            divPointHtml = '<div style="width: 200px; height: 134px;pointer-events:none; background: url(' + this._core.defaultValue(option.url, 'http://36.7.136.132:1988/sdkdemo/src/static/image/divpoint1.png') + ');">\n' +
                '                   <div class="title" style="position: absolute;top: 22px;left: 70px;font-size: 14px;text-align: left;color: rgba(255,255,255,1);text-shadow: 0 0 9px rgba(0,0,0,.75)">' + this._core.defaultValue(option.name, 'SmartEarth') + '</div>\n' +
                '           </div>';
        }
        Element.innerHTML = this._core.defaultValue(option.innerHTML, divPointHtml);
        item.setPosition(position);

        this._map.addOverlay(item);

        return {
            isShow: true,
            item: item,
            Element: Element,
            show: function (visiable) {
                this.isShow = visiable;
                this.Element.style.display = visiable ? 'block' : 'none';
            },
            setPosition: function (position) {
                this.item.setPosition(position);
            }
        }
    }

    /**
   * 结束绘制
   */
    _.prototype.end = function () {
        this.draw && this._map.removeInteraction(this.draw);
        this.draw = undefined;
    }

    /**
     * 暂停/继续绘制
     */
    _.prototype.pause = function () {
        this.draw && this.draw.setActive(!this.draw.getActive());
    }

    /**
    * 清除
    */
    _.prototype.clear = function () {
        this.draw && this._map.removeInteraction(this.draw);
        this._map.removeLayer(this.vector);
        this.draw = undefined;
        this.vector = undefined;
    }
    return _;
});
/**
 *
 *      实现功能：创建线。
 *      
 *      创建人员：薛鹏
 *
 *      创建日期：2020-03-17
 *
 *      参与人员：薛鹏
 *
 *      最后修改人员：薛鹏
 *
 *      最后修改时间：2020-03-17
 *
 * */
define('SGWorld/Creator/Polyline',['../Core/Core'], function (Core) {
    'use strict';
    /**
    *
    * 这个方法用于创建线。
    *
    * @alias addLayer 
    * @constructor
    *
    */
    function _(map) {
        this._map = map;
        this._core = new Core();
    }

    /**
    * 这个方法用于添加线对象
    *@param {String} [name] 名称
    *@param {String} [url] url。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    _.prototype.createPolyline = function (option) {
        !option && (option = {});

        let layerOption = {
            source: new ol.source.Vector()
        }

        layerOption = this._core.extend(layerOption, option, true);

        if (!layerOption.style) {
            layerOption.style = new ol.style.Style({
                stroke: new ol.style.Stroke({
                    color: this._core.defaultValue(layerOption.color, '#ffcc33'),
                    width: this._core.defaultValue(layerOption.width, 2),
                })
            });
        }
        this.vector = new ol.layer.Vector(layerOption);
        this._map.addLayer(this.vector);

        this.draw = new ol.interaction.Draw({
            source: layerOption.source,
            type: "LineString"
        });
        this._map.addInteraction(this.draw);
        return this;
    }

    /**
   * 结束绘制
   */
    _.prototype.end = function () {
        this.draw && this._map.removeInteraction(this.draw);
        this.draw = undefined;
    }

    /**
     * 暂停/继续绘制
     */
    _.prototype.pause = function () {
        this.draw && this.draw.setActive(!this.draw.getActive());
    }

    /**
    * 清除
    */
    _.prototype.clear = function () {
        this.draw && this._map.removeInteraction(this.draw);
        this._map.removeLayer(this.vector);
        this.draw = undefined;
        this.vector = undefined;
    }
    return _;
});
/**
 *
 *      实现功能：创建面。
 *      
 *      创建人员：薛鹏
 *
 *      创建日期：2020-03-17
 *
 *      参与人员：薛鹏
 *
 *      最后修改人员：薛鹏
 *
 *      最后修改时间：2020-03-17
 *
 * */
define('SGWorld/Creator/Polygon',['../Core/Core'], function (Core) {
    'use strict';
    /**
    *
    * 这个方法用于创建面。
    *
    * @alias addLayer 
    * @constructor
    *
    */
    function _(map) {
        this._map = map;
        this._core = new Core();
    }

    /**
    * 这个方法用于添加面对象
    *@param {String} [name] 名称
    *@param {String} [url] url。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    _.prototype.createPolygon = function (option) {
        !option && (option = {});

        let layerOption = {
            source: new ol.source.Vector()
        }

        layerOption = this._core.extend(layerOption, option, true);

        if (!layerOption.style) {
            layerOption.style = new ol.style.Style({
                fill: new ol.style.Fill({
                    color: this._core.defaultValue(layerOption.color, 'rgba(255, 255, 255, 0.2)')
                }),
                stroke: new ol.style.Stroke({
                    color: this._core.defaultValue(layerOption.outlineColor, '#ffcc33'),
                    width: this._core.defaultValue(layerOption.outlineWidth, 2),
                })
            });
        }
        this.vector = new ol.layer.Vector(layerOption);
        this._map.addLayer(this.vector);
        
        this.draw = new ol.interaction.Draw({
            source: layerOption.source,
            type: "Polygon"
        });
        this._map.addInteraction(this.draw);
        return this;
    }

    /**
   * 结束绘制
   */
    _.prototype.end = function () {
        this.draw && this._map.removeInteraction(this.draw);
        this.draw = undefined;
    }

    /**
     * 暂停/继续绘制
     */
    _.prototype.pause = function () {
        this.draw && this.draw.setActive(!this.draw.getActive());
    }

    /**
    * 清除
    */
    _.prototype.clear = function () {
        this.draw && this._map.removeInteraction(this.draw);
        this._map.removeLayer(this.vector);
        this.draw = undefined;
        this.vector = undefined;
    }
    return _;
});
/**
 *
 *      实现功能：创建圆。
 *      
 *      创建人员：薛鹏
 *
 *      创建日期：2020-03-17
 *
 *      参与人员：薛鹏
 *
 *      最后修改人员：薛鹏
 *
 *      最后修改时间：2020-03-17
 *
 * */
define('SGWorld/Creator/Circle',['../Core/Core'], function (Core) {
    'use strict';
    /**
    *
    * 这个方法用于创建圆。
    *
    * @alias addLayer 
    * @constructor
    *
    */
    function _(map) {
        this._map = map;
        this._core = new Core();
    }

    /**
    * 这个方法用于添加圆对象
    *@param {String} [name] 名称
    *@param {String} [url] url。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    _.prototype.createCircle = function () {
        var source = new ol.source.Vector();
        this.vector = new ol.layer.Vector({
            source: source,
            style: new ol.style.Style({
                fill: new ol.style.Fill({
                    color: 'rgba(255, 255, 255, 0.2)'
                }),
                stroke: new ol.style.Stroke({
                    color: '#ffcc33',
                    width: 2
                }),
                image: new ol.style.Circle({
                    radius: 7,
                    fill: new ol.style.Fill({
                        color: '#ffcc33'
                    })
                })
            })
        });
        this._map.addLayer(this.vector);
        var value = "Circle";
        this.draw = new ol.interaction.Draw({
            source: source,
            type: value
        });
        this._map.addInteraction(this.draw);
        return this;
    }

    /**
   * 结束绘制
   */
    _.prototype.end = function () {
        this.draw && this._map.removeInteraction(this.draw);
        this.draw = undefined;
    }

    /**
     * 暂停/继续绘制
     */
    _.prototype.pause = function () {
        this.draw && this.draw.setActive(!this.draw.getActive());
    }
    
    /**
    * 清除
    */
    _.prototype.clear = function () {
        this.draw && this._map.removeInteraction(this.draw);
        this._map.removeLayer(this.vector);
        this.draw = undefined;
        this.vector = undefined;
    }
    return _;
});
/**
 *
 *      实现功能：创建矩形。
 *      
 *      创建人员：张丹钊
 *
 *      创建日期：2020-03-30
 *
 *      参与人员：张丹钊
 *
 *      最后修改人员：张丹钊
 *
 *      最后修改时间：2020-03-30
 *
 * */
define('SGWorld/Creator/Rectangle',['../Core/Core'], function (Core) {
    'use strict';
    /**
    *
    * 这个方法用于创建矩形
    *
    * @alias createRectangle 
    * @constructor
    *
    */
    function _(map) {
        this._map = map;
        this._core = new Core();
    }

    /**
    * 这个方法用于添加矩形对象
    * @param {Object} [option] 图层参数。
    */
    _.prototype.createRectangle = function (option) {
        !option && (option = {});

        let layerOption = {
            source: new ol.source.Vector()
        }

        layerOption = this._core.extend(layerOption, option, true);

        if (!layerOption.style) {
            let style = {};
            if (layerOption.fillColor) {
                style.fill = new ol.style.Fill({
                    color: layerOption.fillColor
                });
            }
            if (layerOption.lineColor || layerOption.width) {
                style.stroke = new ol.style.Stroke({
                    color: this._core.defaultValue(layerOption.lineColor, 'rgba(0, 0, 255, 1.0)'),
                    width: this._core.defaultValue(layerOption.width, 2)
                });
            }
            if (layerOption.textColor || layerOption.textScale) {
                style.text = new ol.style.Text({
                    fill: this._core.defaultValue(layerOption.textColor, '#333'),
                    scale: this._core.defaultValue(layerOption.textScale, 1)
                });
            }
            if (style.fill || style.stroke || style.text) {
                layerOption.style = new ol.style.Style(style);
            } else {
                layerOption.style = new ol.style.Style({
                    fill: new ol.style.Fill({
                        color: 'rgba(255, 255, 255, 0.2)'
                    }),
                    stroke: new ol.style.Stroke({
                        color: '#ffcc33',
                        width: 2
                    }),
                    image: new ol.style.Circle({
                        radius: 7,
                        fill: new ol.style.Fill({
                            color: '#ffcc33'
                        })
                    })
                });
            }
        }
        this.vector = new ol.layer.Vector(layerOption);
        this._map.addLayer(this.vector);

        this.draw = new ol.interaction.Draw({
            source: layerOption.source,
            type: "Circle",
            geometryFunction: ol.interaction.Draw.createBox()
        });
        this._map.addInteraction(this.draw);

        return this;
    }

    /**
    * 这个方法用于添加正方形象
    * @param {Object} [option] 图层参数。
    */
    _.prototype.createSquare = function (option) {
        !option && (option = {});

        let layerOption = {
            source: new ol.source.Vector()
        }

        layerOption = this._core.extend(layerOption, option, true);

        if (!layerOption.style) {
            let style = {};
            if (layerOption.fillColor) {
                style.fill = new ol.style.Fill({
                    color: layerOption.fillColor
                });
            }
            if (layerOption.lineColor || layerOption.width) {
                style.stroke = new ol.style.Stroke({
                    color: this._core.defaultValue(layerOption.lineColor, 'rgba(0, 0, 255, 1.0)'),
                    width: this._core.defaultValue(layerOption.width, 2)
                });
            }
            if (layerOption.text || layerOption.textColor || layerOption.textScale) {
                style.text = new ol.style.Text({
                    text: this._core.defaultValue(layerOption.text, '新建文本'),
                    fill: this._core.defaultValue(layerOption.textColor, '#333'),
                    scale: this._core.defaultValue(layerOption.textScale, 1)
                });
            }
            if (layerOption.image) {
                style.image = new ol.style.Icon({
                    src: layerOption.image,
                    scale: this._core.defaultValue(layerOption.imageScale, 1)
                });
            }
            if (style.fill || style.stroke || style.text || style.image) {
                layerOption.style = new ol.style.Style(style);
            } else {
                layerOption.style = new ol.style.Style({
                    fill: new ol.style.Fill({
                        color: 'rgba(255, 255, 255, 0.2)'
                    }),
                    stroke: new ol.style.Stroke({
                        color: '#ffcc33',
                        width: 2
                    }),
                    image: new ol.style.Circle({
                        radius: 7,
                        fill: new ol.style.Fill({
                            color: '#ffcc33'
                        })
                    })
                });
            }
        }
        this.vector = new ol.layer.Vector(layerOption);
        this._map.addLayer(this.vector);

        this.draw = new ol.interaction.Draw({
            source: layerOption.source,
            type: "Circle",
            geometryFunction: ol.interaction.Draw.createRegularPolygon(4)
        });
        this._map.addInteraction(this.draw);

        return this;
    }

    /**
   * 结束绘制
   */
    _.prototype.end = function () {
        this.draw && this._map.removeInteraction(this.draw);
        this.draw = undefined;
    }

    /**
     * 暂停/继续绘制
     */
    _.prototype.pause = function () {
        this.draw && this.draw.setActive(!this.draw.getActive());
    }

    /**
    * 清除
    */
    _.prototype.clear = function () {
        this.draw && this._map.removeInteraction(this.draw);
        this._map.removeLayer(this.vector);
        this.draw = undefined;
        this.vector = undefined;
    }

    return _;
});
/**
 *
 *      实现功能：创建星形。
 *      
 *      创建人员：张丹钊
 *
 *      创建日期：2020-03-30
 *
 *      参与人员：张丹钊
 *
 *      最后修改人员：张丹钊
 *
 *      最后修改时间：2020-03-30
 *
 * */
define('SGWorld/Creator/Star',['../Core/Core'], function (Core) {
    'use strict';
    /**
    *
    * 这个方法用于创建星形
    *
    * @alias createStar 
    * @constructor
    *
    */
    function _(map) {
        this._map = map;
        this._core = new Core();
    }

    /**
    * 这个方法用于创建星形对象
    * @param {Object} [option] 图层参数。
    */
    _.prototype.createStar = function (option) {
        !option && (option = {});

        let layerOption = {
            source: new ol.source.Vector()
        }

        layerOption = this._core.extend(layerOption, option, true);

        if (!layerOption.style) {
            let style = {};
            if (layerOption.fillColor) {
                style.fill = new ol.style.Fill({
                    color: layerOption.fillColor
                });
            }
            if (layerOption.lineColor || layerOption.width) {
                style.stroke = new ol.style.Stroke({
                    color: this._core.defaultValue(layerOption.lineColor, 'rgba(0, 0, 255, 1.0)'),
                    width: this._core.defaultValue(layerOption.width, 2)
                });
            }
            if (layerOption.textColor || layerOption.textScale) {
                style.text = new ol.style.Text({
                    fill: this._core.defaultValue(layerOption.textColor, '#333'),
                    scale: this._core.defaultValue(layerOption.textScale, 1)
                });
            }
            if (style.fill || style.stroke || style.text) {
                layerOption.style = new ol.style.Style(style);
            } else {
                layerOption.style = new ol.style.Style({
                    fill: new ol.style.Fill({
                        color: 'rgba(255, 255, 255, 0.2)'
                    }),
                    stroke: new ol.style.Stroke({
                        color: '#ffcc33',
                        width: 2
                    }),
                    image: new ol.style.Circle({
                        radius: 7,
                        fill: new ol.style.Fill({
                            color: '#ffcc33'
                        })
                    })
                });
            }
        }
        this.vector = new ol.layer.Vector(layerOption);
        this._map.addLayer(this.vector);

        this.draw = new ol.interaction.Draw({
            source: layerOption.source,
            type: "Circle",
            geometryFunction: function (coordinates, geometry) {
                if (!geometry) {
                    //根据绘制的坐标返回自定义的geometry，随意拓展 
                    geometry = new ol.geom.Polygon(coordinates);
                }
                var center = coordinates[0];
                var last = coordinates[1];
                var dx = center[0] - last[0];
                var dy = center[1] - last[1];
                var radius = Math.sqrt(dx * dx + dy * dy);
                var rotation = Math.atan2(dy, dx);
                var newCoordinates = [];
                var numPoints = 12;
                for (var i = 0; i < numPoints; ++i) {
                    var angle = rotation + i * 2 * Math.PI / numPoints;
                    var fraction = i % 2 === 0 ? 1 : 0.5;
                    var offsetX = radius * fraction * Math.cos(angle);
                    var offsetY = radius * fraction * Math.sin(angle);
                    newCoordinates.push([center[0] + offsetX, center[1] + offsetY]);
                }
                newCoordinates.push(newCoordinates[0].slice());
                geometry.setCoordinates([newCoordinates]);
                return geometry;
            }
        });
        this._map.addInteraction(this.draw);

        return this;
    }

    /**
   * 结束绘制
   */
    _.prototype.end = function () {
        this.draw && this._map.removeInteraction(this.draw);
        this.draw = undefined;
    }

    /**
     * 暂停/继续绘制
     */
    _.prototype.pause = function () {
        this.draw && this.draw.setActive(!this.draw.getActive());
    }
    
    /**
    * 清除
    */
    _.prototype.clear = function () {
        this.draw && this._map.removeInteraction(this.draw);
        this._map.removeLayer(this.vector);
        this.draw = undefined;
        this.vector = undefined;
    }

    return _;
});
/**
 *
 *      实现功能：创建军事标绘。
 *      
 *      创建人员：张丹钊
 *
 *      创建日期：2020-03-30
 *
 *      参与人员：张丹钊
 *
 *      最后修改人员：张丹钊
 *
 *      最后修改时间：2020-03-30
 *
 * */
define('SGWorld/Creator/MilitaryObject',['../Core/Core'], function (Core) {
    'use strict';
    /**
    *
    * 这个方法用于创建军事标绘
    *
    * @alias createMilitaryObject 
    * @constructor
    *
    */
    function _(map) {
        this._map = map;
        this._core = new Core();
    }

    /**
    * 这个方法用于创建军事标绘
    * @param {String} [type] 军标类型（StraightArrow:粗直箭头/SwallowtailArrow:燕尾箭头/PincerArrow:钳击箭头/RoundRectangle:圆角矩形/GatheringArea:聚集区/Bow:弓形/Sector:扇形/BezierLine:贝塞尔曲线/BezierArrow:贝塞尔箭头）。
    * @param {Object} [option] 图层参数。
    */
    _.prototype.createMilitaryObject = function (type, option) {
        !option && (option = {});

        let layerOption = {
            source: new ol.source.Vector()
        }

        layerOption = this._core.extend(layerOption, option, true);

        if (!layerOption.style) {
            let style = {};
            if (layerOption.fillColor) {
                style.fill = new ol.style.Fill({
                    color: layerOption.fillColor
                });
            }
            if (layerOption.lineColor || layerOption.width) {
                style.stroke = new ol.style.Stroke({
                    color: this._core.defaultValue(layerOption.lineColor, 'rgba(0, 0, 255, 1.0)'),
                    width: this._core.defaultValue(layerOption.width, 2)
                });
            }
            if (layerOption.textColor || layerOption.textScale) {
                style.text = new ol.style.Text({
                    fill: this._core.defaultValue(layerOption.textColor, '#333'),
                    scale: this._core.defaultValue(layerOption.textScale, 1)
                });
            }
            if (style.fill || style.stroke || style.text) {
                layerOption.style = new ol.style.Style(style);
            } else {
                layerOption.style = new ol.style.Style({
                    fill: new ol.style.Fill({
                        color: 'rgba(255, 0, 0, 0.5)'
                    }),
                    stroke: new ol.style.Stroke({
                        color: '#ffcc33',
                        width: 3
                    }),
                    image: new ol.style.Circle({
                        radius: 7,
                        fill: new ol.style.Fill({
                            color: '#ffcc33'
                        })
                    })
                });
            }
        }
        this.vector = new ol.layer.Vector(layerOption);
        this._map.addLayer(this.vector);
        this.startDraw(type, layerOption.source);
        return this;
    }

    /**
     * 开始绘制
     */
    _.prototype.startDraw = function (type, source) {
        let _this = this;
        !type && (type = 'StraightArrow');

        switch (type) {
            //圆角矩形
            case 'RoundRectangle':
            //聚集区
            case 'GatheringArea':
            //粗直箭头
            case 'StraightArrow':
            //燕尾箭头
            case 'SwallowtailArrow':
                this.draw = new ol.interaction.Draw({
                    source: source,
                    type: "Circle",
                    geometryFunction: function (coordinates, geometry) {
                        if (!geometry) {
                            //根据绘制的坐标返回自定义的geometry，随意拓展 
                            geometry = new ol.geom.Polygon(coordinates);
                        }
                        let newCoordinates = _this.getGeometry(type, coordinates);
                        newCoordinates.push(newCoordinates[0]);
                        geometry.setCoordinates([newCoordinates]);
                        return geometry;
                    }
                });

                break;
            //钳击箭头
            case 'PincerArrow':
                this.draw = new ol.interaction.Draw({
                    source: source,
                    type: "LineString",
                    minPoints: 3,
                    maxPoints: 5,
                    geometryFunction: function (coordinates, geometry) {
                        if (!geometry) {
                            //根据绘制的坐标返回自定义的geometry，随意拓展 
                            geometry = new ol.geom.Polygon(coordinates);
                        }
                        if (coordinates.length > 2 && coordinates[1] !== coordinates[2]) {
                            let newCoordinates = _this.getGeometry(type, coordinates);
                            newCoordinates.push(newCoordinates[0]);
                            geometry.setCoordinates([newCoordinates]);
                        } else {
                            geometry.setCoordinates([coordinates]);
                        }
                        
                        return geometry;
                    }
                });
                break;
            //扇形
            case 'Sector':
            //弓形
            case 'Bow':
                this.draw = new ol.interaction.Draw({
                    source: source,
                    type: "LineString",
                    minPoints: 3,
                    maxPoints: 3,
                    geometryFunction: function (coordinates, geometry) {
                        if (!geometry) {
                            //根据绘制的坐标返回自定义的geometry，随意拓展 
                            geometry = new ol.geom.Polygon(coordinates);
                        }
                        if (coordinates.length > 2 && coordinates[1] !== coordinates[2]) {
                            let newCoordinates = _this.getGeometry(type, coordinates);
                            newCoordinates.push(newCoordinates[0]);
                            geometry.setCoordinates([newCoordinates]);
                        } else {
                            geometry.setCoordinates([coordinates]);
                        }
                        return geometry;
                    }
                });
                break;
            case 'BezierLine'://贝塞尔曲线
            case 'BezierArrow'://贝塞尔箭头
                this.draw = new ol.interaction.Draw({
                    source: source,
                    type: "LineString",
                    geometryFunction: function (coordinates, geometry) {
                        if (!geometry) {
                            //根据绘制的坐标返回自定义的geometry，随意拓展 
                            geometry = new ol.geom.LineString(coordinates);
                        }

                        let newCoordinates = _this.getGeometry(type, coordinates);
                        geometry.setCoordinates(newCoordinates);

                        return geometry;
                    }
                });
                break;
        }
        this.draw && this._map.addInteraction(this.draw);
    }

    /**
     * 获取几何对象
     */
    _.prototype.getGeometry = function (type, anchorpoints) {
        switch (type) {
            case 'StraightArrow': return this.calculateTwoPoints(anchorpoints);//粗直箭头
            case 'SwallowtailArrow': return this.computeSwallowtailArrow(anchorpoints);//燕尾箭头
            case 'RoundRectangle': return this.computeRoundedRectanglePoints(anchorpoints);//圆角矩形
            case 'Bow': return this.computeBowPoints(anchorpoints);//弓形
            case 'Sector': return this.computeSectorPoints(anchorpoints);//扇形
            case 'GatheringArea':
                let points = this.computeGatheringPlacePoints(anchorpoints);
                let _points = createCloseCardinal(points);
                return calculatePointsFBZ3(_points, 100);//聚集区
            case 'PincerArrow': return algorithm.doubleArrow(anchorpoints);//钳击箭头
            case 'BezierLine': return this.createBezierPoints(anchorpoints);//贝塞尔曲线
            case 'BezierArrow': return this.createBezierPoints(anchorpoints);//贝塞尔箭头
            default: return this.calculateTwoPoints(anchorpoints);
        }
    }

    /**
     * 获取粗直箭头坐标点
     */
    _.prototype.calculateTwoPoints = function (anchorpoints) {
        var ratio = 6
        var pointS = {   //箭头起点
            x: anchorpoints[0][0],
            y: anchorpoints[0][1],
        }
        var pointE = {   //箭头终点
            x: anchorpoints[1][0],
            y: anchorpoints[1][1],
        }
        var controlPois = [];
        var v_based = { x: pointE.x - pointS.x, y: pointE.y - pointS.y };//计算基准向量
        var l = Math.sqrt((pointE.x - pointS.x) * (pointE.x - pointS.x) + (pointE.y - pointS.y) * (pointE.y - pointS.y));//计算箭头长度
        var w = l / ratio;//箭头宽度
        var x_ = pointS.x + 5 * (pointE.x - pointS.x) / ratio;//箭头前端三角形中点坐标x
        var y_ = pointS.y + 5 * (pointE.y - pointS.y) / ratio;//箭头前端三角形中点坐标y
        var v_lr = calculateVector(v_based, Math.PI / 2, w / 2);
        var v_l = v_lr[0];
        var v_r = v_lr[1];
        var point1 = [pointS.x + v_l.x, pointS.y + v_l.y];
        var point2 = [x_ + v_l.x, y_ + v_l.y];
        var point3 = [x_ + 2 * v_l.x, y_ + 2 * v_l.y];
        var point4 = [pointE.x, pointE.y];
        var point5 = [x_ + 2 * v_r.x, y_ + 2 * v_r.y];
        var point6 = [x_ + v_r.x, y_ + v_r.y];
        var point7 = [pointS.x + v_r.x, pointS.y + v_r.y];
        controlPois.push(point1, point2, point3, point4, point5, point6, point7);
        return controlPois;
    }


    /**
     * 计算燕尾箭头特征点坐标
     * @param anchorpoints
     * @returns {any[]}
     * @private
     */
    _.prototype.computeSwallowtailArrow = function (anchorpoints) {
        var x0 = anchorpoints[0][0];
        var y0 = anchorpoints[0][1];
        var x1 = anchorpoints[1][0];
        var y1 = anchorpoints[1][1];
        var xt = (15.8 * x1 + 3.2 * x0) / 19;
        var yt = (15.8 * y1 + 3.2 * y0) / 19;
        var ap = new Array(7);
        ap[0] = [x1, y1];
        ap[1] = [xt + 0.85 / 3.2 * (y1 - yt), yt - 0.85 / 3.2 * (x1 - xt)];
        ap[2] = [xt + 0.25 / 3.2 * (y1 - yt), yt - 0.25 / 3.2 * (x1 - xt)];
        ap[3] = [x0 + 1.6 / 19 * (y1 - y0), y0 - 1.6 / 19 * (x1 - x0)];
        ap[4] = [(3.2 * x1 + 15.8 * x0) / 19, (3.2 * y1 + 15.8 * y0) / 19];
        ap[5] = [x0 - 1.6 / 19 * (y1 - y0), y0 + 1.6 / 19 * (x1 - x0)];
        ap[6] = [xt - 0.25 / 3.2 * (y1 - yt), yt + 0.25 / 3.2 * (x1 - xt)];
        ap[7] = [xt - 0.85 / 3.2 * (y1 - yt), yt + 0.85 / 3.2 * (x1 - xt)];
        return ap;
    };

    /**
     * 根据基准向量、夹角、长度计算指定向量
     * @param v
     * @param theta
     * @param d
     * @returns {*[]}
     */
    function calculateVector(v, theta, d) {
        if (!theta) theta = Math.PI / 2;
        if (!d) d = 1;

        var x_1;
        var x_2;
        var y_1;
        var y_2;
        var v_l;
        var v_r;

        var d_v = Math.sqrt(v.x * v.x + v.y * v.y);

        if (v.y == 0) {
            x_1 = x_2 = d_v * d * Math.cos(theta) / v.x;
            if (v.x > 0) {
                y_1 = Math.sqrt(d * d - x_1 * x_1);
                y_2 = -y_1;
            }
            else if (v.x < 0) {
                y_2 = Math.sqrt(d * d - x_1 * x_1);
                y_1 = -y_2;
            }
            v_l = { x: x_1, y: y_1 };
            v_r = { x: x_2, y: y_2 };
        }
        else {
            var n = -v.x / v.y;
            var m = d * d_v * Math.cos(theta) / v.y;
            var a = 1 + n * n;
            var b = 2 * n * m;
            var c = m * m - d * d;
            x_1 = (-b - Math.sqrt(b * b - 4 * a * c)) / (2 * a);
            x_2 = (-b + Math.sqrt(b * b - 4 * a * c)) / (2 * a);
            y_1 = n * x_1 + m;
            y_2 = n * x_2 + m;
            if (v.y >= 0) {
                v_l = { x: x_1, y: y_1 };
                v_r = { x: x_2, y: y_2 };
            }
            else if (v.y < 0) {
                v_l = { x: x_2, y: y_2 };
                v_r = { x: x_1, y: y_1 };
            }
        }
        return [v_l, v_r];
    }

    /**
     * 根据输入的两点计算向量的角度
     * @param a1
     * @param a2
     * @returns {*}
     */
    function calculateAngle(a1, a2) {
        var a = { x: a2.x - a1.x, y: a2.y - a1.y };
        var theta = Math.atan2(a.y, a.x);
        if (theta < 0) {
            theta = theta + 2 * Math.PI;
        }
        return theta;
    }
    /**
     *计算扇形特征点
    * @param anchor
    * @returns {Array}
    * @private
    */
    _.prototype.computeSectorPoints = function (_anchor) {
        let anchor = [];
        anchor.push({
            x: _anchor[0][0],
            y: _anchor[0][1],
        });
        anchor.push({
            x: _anchor[1][0],
            y: _anchor[1][1],
        });
        anchor.push({
            x: _anchor[2][0],
            y: _anchor[2][1],
        });

        var theta1 = calculateAngle(anchor[0], anchor[1]);
        var theta2 = calculateAngle(anchor[0], anchor[2]);
        if (theta1 > theta2) {
            theta2 = 2 * Math.PI + theta2;
        }
        var step = Math.PI / 180;
        var radius = theta1;
        var points = [_anchor[0]];
        var r = Math.sqrt((anchor[1].x - anchor[0].x) * (anchor[1].x - anchor[0].x) + (anchor[1].y - anchor[0].y) * (anchor[1].y - anchor[0].y));
        for (var i = 0; i < Math.abs(theta1 - theta2); i += step) {
            var X = anchor[0].x + r * Math.cos(radius);
            var Y = anchor[0].y + r * Math.sin(radius);
            radius = radius + step;
            radius = radius < 0 ? 2 * Math.PI + radius : radius;
            radius = radius > 2 * Math.PI ? radius - 2 * Math.PI : radius;
            points.push([X, Y]);
        }
        return points;
    }

    /**
     * 计算弓形特征点
     * @param anchorpoints
     * @returns {Array}
     * @private
     */
    _.prototype.computeBowPoints = function (_anchor) {
        //根据三个点到圆心的距离相等
        let anchor = [];
        anchor.push({
            x: _anchor[0][0],
            y: _anchor[0][1],
        });
        anchor.push({
            x: _anchor[1][0],
            y: _anchor[1][1],
        });
        anchor.push({
            x: _anchor[2][0],
            y: _anchor[2][1],
        });
        var A1 = 2 * (anchor[1].x - anchor[0].x);
        var B1 = 2 * (anchor[1].y - anchor[0].y);
        var C1 = anchor[1].x * anchor[1].x + anchor[1].y * anchor[1].y - anchor[0].x * anchor[0].x - anchor[0].y * anchor[0].y;
        var A2 = 2 * (anchor[2].x - anchor[1].x);
        var B2 = 2 * (anchor[2].y - anchor[1].y);
        var C2 = anchor[2].x * anchor[2].x + anchor[2].y * anchor[2].y - anchor[1].x * anchor[1].x - anchor[1].y * anchor[1].y;
        var o_x = (C1 * B2 - C2 * B1) / (A1 * B2 - A2 * B1);
        var o_y = (A1 * C2 - A2 * C1) / (A1 * B2 - A2 * B1);
        var o = { x: o_x, y: o_y };
        var r = Math.sqrt((anchor[0].x - o_x) * (anchor[0].x - o_x) + (anchor[0].y - o_y) * (anchor[0].y - o_y));
        var theta1 = calculateAngle(o, anchor[0]);
        var theta2 = calculateAngle(o, anchor[1]);
        var theta3 = calculateAngle(o, anchor[2]);
        var step = Math.PI / 180;
        var radius = undefined;
        var points = [];
        if ((theta1 < theta3 && theta3 < theta2) || (theta2 < theta3 && theta3 < theta1)) {
            radius = theta1 < theta2 ? theta1 : theta2;
            for (var i = 0; i < Math.abs(theta1 - theta2); i += step) {
                var X = o_x + r * Math.cos(radius);
                var Y = o_y + r * Math.sin(radius);
                radius = radius + step;
                radius = radius < 0 ? 2 * Math.PI + radius : radius;
                radius = radius > 2 * Math.PI ? 2 * Math.PI - radius : radius;
                points.push([X, Y]);
            }
        }
        else {
            radius = theta1 > theta2 ? theta1 : theta2;
            for (var i = 0; i < (2 * Math.PI - Math.abs(theta1 - theta2)); i += step) {
                var X = o_x + r * Math.cos(radius);
                var Y = o_y + r * Math.sin(radius);
                radius = radius + step;
                radius = radius < 0 ? 2 * Math.PI + radius : radius;
                radius = radius > 2 * Math.PI ? radius - 2 * Math.PI : radius;
                points.push([X, Y]);
            }
        }
        return points;
    }

    /**
   * 计算圆角矩形特征点
   * @param anchor
   * @returns {Array}
   * @private
   */
    _.prototype.computeRoundedRectanglePoints = function (anchor) {
        var o_x = (anchor[0][0] + anchor[1][0]) / 2;
        var o_y = (anchor[0][1] + anchor[1][1]) / 2;
        var o = { x: o_x, y: o_y };
        //a为矩形的长边，b为矩形的短边
        var a = Math.abs(anchor[0][0] - anchor[1][0]);
        var b = Math.abs(anchor[0][1] - anchor[1][1]);
        var r = 1 / 10 * Math.min(a, b);
        //从左上点开始，顺时针求四个圆弧的圆心
        var o1_x = o_x - a / 2 + r;
        var o1_y = o_y - b / 2 + r;
        var o1 = { x: o1_x, y: o1_y };
        var o2 = { x: o_x + a / 2 - r, y: o_y - b / 2 + r };
        var o3 = { x: o_x + a / 2 - r, y: o_y + b / 2 - r };
        var o4 = { x: o_x - a / 2 + r, y: o_y + b / 2 - r };
        //从左上角开始画圆弧
        var step = Math.PI / 180;
        var points1 = [];
        var theta1 = Math.PI;
        var theta2 = 3 / 2 * Math.PI;
        var radius1 = theta1;
        for (var i = 0; i < Math.abs(theta1 - theta2); i += step) {
            var X = o1.x + r * Math.cos(radius1);
            var Y = o1.y + r * Math.sin(radius1);
            radius1 = radius1 + step;
            radius1 = radius1 < 0 ? 2 * Math.PI + radius1 : radius1;
            radius1 = radius1 > 2 * Math.PI ? 2 * Math.PI - radius1 : radius1;
            points1.push([X, Y]);
        }
        var points2 = points1;
        var theta3 = Math.PI * 3 / 2;
        var theta4 = 2 * Math.PI;
        var radius2 = theta3;
        for (var i = 0; i < Math.abs(theta3 - theta4); i += step) {
            var X = o2.x + r * Math.cos(radius2);
            var Y = o2.y + r * Math.sin(radius2);
            radius2 = radius2 + step;
            radius2 = radius2 < 0 ? 2 * Math.PI + radius2 : radius2;
            radius2 = radius2 > 2 * Math.PI ? 2 * Math.PI - radius2 : radius2;
            points2.push([X, Y]);
        }
        var points3 = points2;
        var theta5 = 0;
        var theta6 = 1 / 2 * Math.PI;
        var radius3 = theta5;
        for (var i = 0; i < Math.abs(theta5 - theta6); i += step) {
            var X = o3.x + r * Math.cos(radius3);
            var Y = o3.y + r * Math.sin(radius3);
            radius3 = radius3 + step;
            radius3 = radius3 < 0 ? 2 * Math.PI + radius3 : radius3;
            radius3 = radius3 > 2 * Math.PI ? 2 * Math.PI - radius3 : radius3;
            points3.push([X, Y]);
        }
        var points = points3;
        var theta7 = 1 / 2 * Math.PI;
        var theta8 = Math.PI;
        var radius4 = theta7;
        for (var i = 0; i < Math.abs(theta7 - theta8); i += step) {
            var X = o4.x + r * Math.cos(radius4);
            var Y = o4.y + r * Math.sin(radius4);
            radius4 = radius4 + step;
            radius4 = radius4 < 0 ? 2 * Math.PI + radius4 : radius4;
            radius4 = radius4 > 2 * Math.PI ? 2 * Math.PI - radius4 : radius4;
            points.push([X, Y]);
        }
        return points;
    }

    /**
     * 计算聚集区特征点
     * @param anchorpoints
     * @returns {Array}
     * @private
     */
    _.prototype.computeGatheringPlacePoints = function (anchorpoints) {
        var points = [];
        if (anchorpoints.length == 2) {
            var originP = {
                x: anchorpoints[0][0],
                y: anchorpoints[0][1]
            };
            var lastP = {
                x: anchorpoints[anchorpoints.length - 1][0],
                y: anchorpoints[anchorpoints.length - 1][1]
            };
            var vectorOL = { x: lastP.x - originP.x, y: lastP.y - originP.y };
            var dOL = Math.sqrt(vectorOL.x * vectorOL.x + vectorOL.y * vectorOL.y);
            var v_O_P1_lr = calculateVector(vectorOL, Math.PI / 3, Math.sqrt(3) / 12 * dOL);
            var originP_P1 = v_O_P1_lr[1];
            var p1 = { x: originP.x + originP_P1.x, y: originP.y + originP_P1.y };
            var p2 = { x: (originP.x + lastP.x) / 2, y: (originP.y + lastP.y) / 2 };
            var v_L_P3_lr = calculateVector(vectorOL, Math.PI * 2 / 3, Math.sqrt(3) / 12 * dOL);
            var lastP_P3 = v_L_P3_lr[1];
            var p3 = { x: lastP.x + lastP_P3.x, y: lastP.y + lastP_P3.y };
            var v_O_P5_lr = calculateVector(vectorOL, Math.PI / 2, 1 / 2 * dOL);
            var v_O_P5 = v_O_P5_lr[0];
            var p5 = { x: v_O_P5.x + p2.x, y: v_O_P5.y + p2.y };
            var p0 = originP;
            var p4 = lastP;
            points.push(p0, p1, p2, p3, p4, p5);
        }
        return points;
    }

    /**
     * 生成闭合的样条点
     * @param points
     * @returns {*}
     */
    function createCloseCardinal(points) {
        if (points == null || points.length < 3) {
            return points;
        }
        //获取起点，作为终点，以闭合曲线。
        var lastP = points[0];
        points.push(lastP);

        //定义传入的点数组，将在点数组中央（每两个点）插入两个控制点
        var cPoints = points;
        //包含输入点和控制点的数组
        var cardinalPoints = [];

        //至少三个点以上
        //这些都是相关资料测出的经验数值
        //定义张力系数，取值在0<t<0.5
        var t = 0.4;
        //为端点张力系数因子，取值在0<b<1
        var b = 0.5;
        //误差控制，是一个大于等于0的数，用于三点非常趋近与一条直线时，减少计算量
        var e = 0.005;

        //传入的点数量，至少有三个，n至少为2
        var n = cPoints.length - 1;
        //从开始遍历到倒数第二个，其中倒数第二个用于计算起点（终点）的插值控制点
        for (var k = 0; k <= n - 1; k++) {
            //计算起点（终点）的左右控制点
            if (k == n - 1) {
                //三个基础输入点
                var p0 = cPoints[n - 1];
                var p1 = cPoints[0];
                var p2 = cPoints[1];
            }
            else {
                var p0 = cPoints[k];
                var p1 = cPoints[k + 1];
                var p2 = cPoints[k + 2];
            }

            //定义p1的左控制点和右控制点
            var p1l = { x: undefined, y: undefined };
            var p1r = { x: undefined, y: undefined };
            //通过p0、p1、p2计算p1点的做控制点p1l和又控制点p1r
            //计算向量p0_p1和p1_p2
            var p0_p1 = { x: p1.x - p0.x, y: p1.y - p0.y };
            var p1_p2 = { x: p2.x - p1.x, y: p2.y - p1.y };
            //并计算模
            var d01 = Math.sqrt(p0_p1.x * p0_p1.x + p0_p1.y * p0_p1.y);
            var d12 = Math.sqrt(p1_p2.x * p1_p2.x + p1_p2.y * p1_p2.y);
            //向量单位化
            var p0_p1_1 = { x: p0_p1.x / d01, y: p0_p1.y / d01 };
            var p1_p2_1 = { x: p1_p2.x / d12, y: p1_p2.y / d12 };
            //计算向量p0_p1和p1_p2的夹角平分线向量
            var p0_p1_p2 = { x: p0_p1_1.x + p1_p2_1.x, y: p0_p1_1.y + p1_p2_1.y };
            //计算向量 p0_p1_p2 的模
            var d012 = Math.sqrt(p0_p1_p2.x * p0_p1_p2.x + p0_p1_p2.y * p0_p1_p2.y);
            //单位化向量p0_p1_p2
            var p0_p1_p2_1 = { x: p0_p1_p2.x / d012, y: p0_p1_p2.y / d012 };
            //判断p0、p1、p2是否共线，这里判定向量p0_p1和p1_p2的夹角的余弦和1的差值小于e就认为三点共线
            var cosE_p0p1p2 = (p0_p1_1.x * p1_p2_1.x + p0_p1_1.y * p1_p2_1.y) / 1;
            //共线
            if (Math.abs(1 - cosE_p0p1p2) < e) {
                //计算p1l的坐标
                p1l.x = p1.x - p1_p2_1.x * d01 * t;
                p1l.y = p1.y - p1_p2_1.y * d01 * t;
                //计算p1r的坐标
                p1r.x = p1.x + p0_p1_1.x * d12 * t;
                p1r.y = p1.y + p0_p1_1.y * d12 * t;
            }
            //非共线
            else {
                //计算p1l的坐标
                p1l.x = p1.x - p0_p1_p2_1.x * d01 * t;
                p1l.y = p1.y - p0_p1_p2_1.y * d01 * t;
                //计算p1r的坐标
                p1r.x = p1.x + p0_p1_p2_1.x * d12 * t;
                p1r.y = p1.y + p0_p1_p2_1.y * d12 * t;
            }

            //记录起点（终点）的左右插值控制点及倒数第二个控制点
            if (k == n - 1) {
                cardinalPoints[0] = p1;
                cardinalPoints[1] = p1r;
                cardinalPoints[(n - 2) * 3 + 2 + 3] = p1l;
                cardinalPoints[(n - 2) * 3 + 2 + 4] = cPoints[n];
            }
            else {
                //记录下这三个控制点
                cardinalPoints[k * 3 + 2 + 0] = p1l;
                cardinalPoints[k * 3 + 2 + 1] = p1;
                cardinalPoints[k * 3 + 2 + 2] = p1r;

            }

        }

        return cardinalPoints;
    }

    /**
     * 计算三阶贝塞尔点
     * @param points
     * @param part
     * @returns {Array}
     */
    function calculatePointsFBZ3(points, part) {
        if (!part) part = 20;
        //获取待拆分的点
        var bezierPts = [];
        var scale = 0.05;

        if (part > 0) {
            scale = 1 / part;
        }

        for (var i = 0; i < points.length - 3;) {
            //起始点
            var pointS = points[i];
            //第一个控制点
            var pointC1 = points[i + 1];
            //第二个控制点
            var pointC2 = points[i + 2];
            //结束点
            var pointE = points[i + 3];

            bezierPts.push(pointS);
            for (var t = 0; t < 1;) {
                //三次贝塞尔曲线公式
                var x = (1 - t) * (1 - t) * (1 - t) * pointS.x + 3 * t * (1 - t) * (1 - t) * pointC1.x + 3 * t * t * (1 - t) * pointC2.x + t * t * t * pointE.x;
                var y = (1 - t) * (1 - t) * (1 - t) * pointS.y + 3 * t * (1 - t) * (1 - t) * pointC1.y + 3 * t * t * (1 - t) * pointC2.y + t * t * t * pointE.y;
                var point = { x: x, y: y };
                bezierPts.push(point);
                t += scale;
            }

            i += 3;
            if (i >= points.length) {
                bezierPts.push(pointS);
            }
        }

        //需要判定一下最后一个点是否存在
        var poRE = bezierPts[bezierPts.length - 1];
        var popE = points[points.length - 1];
        /*if (!poRE.equals(popE)) {
            bezierPts.push(popE.clone());
        }*/
        for (let i = 0; i < bezierPts.length; i++) {
            bezierPts[i] = [bezierPts[i].x, bezierPts[i].y];
        }
        return bezierPts;
    }

    /**
     * 计算贝塞尔曲线特征点
     * @param anchorpoints
     * @param t
     * @returns {{x: number, y: number}}
     * @private
     */
    function _computeBezierPoints(anchorpoints, t) {
        var x = 0, y = 0, z = 0;
        var Binomial_coefficient = _computeBinomial(anchorpoints);
        for (var j = 0; j < anchorpoints.length; j++) {
            var tempPoint = anchorpoints[j];
            x += tempPoint[0] * Math.pow((1 - t), (anchorpoints.length - 1 - j)) * Math.pow(t, j) * Binomial_coefficient[j];
            y += tempPoint[1] * Math.pow((1 - t), (anchorpoints.length - 1 - j)) * Math.pow(t, j) * Binomial_coefficient[j];
        }
        return [x, y];
    }

    /**
     * 获取贝塞尔曲线点
     */
    _.prototype.createBezierPoints = function (anchorpoints) {
        var numpoints = 100
        var points = [];
        for (var i = 0; i <= numpoints; i++) {
            var point = _computeBezierPoints(anchorpoints, i / numpoints)
            points.push(point);
        }
        return points;
    }
    /**
     * 计算二项式系数
     * @param anchorpoints
     * @returns {Array}
     * @private
     */
    function _computeBinomial(anchorpoints) {
        var lens = anchorpoints.length;
        var Binomial_coefficient = [];
        Binomial_coefficient.push(1);
        for (var k = 1; k < lens - 1; k++) {
            var cs = 1, bcs = 1;
            for (var m = 0; m < k; m++) {
                cs = cs * (lens - 1 - m);
                bcs = bcs * (k - m);
            }
            Binomial_coefficient.push(cs / bcs);
        }
        Binomial_coefficient.push(1);
        return Binomial_coefficient;
    }

    let doubleArrowDefualParam = {
        type: "doublearrow",
        headHeightFactor: .25,
        headWidthFactor: .3,
        neckHeightFactor: .85,
        fixPointCount: 4,
        neckWidthFactor: .15
    }
    let tailedAttackArrowDefualParam = {
        headHeightFactor: .18,
        headWidthFactor: .3,
        neckHeightFactor: .85,
        neckWidthFactor: .15,
        tailWidthFactor: .1,
        headTailFactor: .8,
        swallowTailFactor: 1
    };
    let fineArrowDefualParam = {
        tailWidthFactor: 0.15,
        neckWidthFactor: 0.20,
        headWidthFactor: 0.25,
        headAngle: Math.PI / 8.5,
        neckAngle: Math.PI / 13
    };

    //钳击箭头工具
    let algorithm = {
        doubleArrow: function (inputPoint) {
            this.connPoint = null;
            this.tempPoint4 = null;
            this.points = inputPoint;
            var result = {
                controlPoint: null,
                polygonalPoint: null
            };
            //获取已经点击的坐标数
            var t = inputPoint.length;
            if (!(2 > t)) {
                if (2 == t) return inputPoint;
                var o = this.points[0],    //第一个点
                    e = this.points[1],        //第二个点
                    r = this.points[2],        //第三个点
                    t = inputPoint.length; //获取已经点击的坐标数
                //下面的是移动点位后的坐标
                3 == t ? this.tempPoint4 = algorithm.getTempPoint4(o, e, r) : this.tempPoint4 = this.points[3],
                    3 == t || 4 == t ? this.connPoint = P.PlotUtils.mid(o, e) : this.connPoint = this.points[4];
                var n, g;
                P.PlotUtils.isClockWise(o, e, r) ? (n = algorithm.getArrowPoints(o, this.connPoint, this.tempPoint4, !1), g = algorithm.getArrowPoints(this.connPoint, e, r, !0)) : (n = algorithm.getArrowPoints(e, this.connPoint, r, !1), g = algorithm.getArrowPoints(this.connPoint, o, this.tempPoint4, !0));
                var i = n.length,
                    s = (i - 5) / 2,
                    a = n.slice(0, s),
                    l = n.slice(s, s + 5),
                    u = n.slice(s + 5, i),
                    c = g.slice(0, s),
                    p = g.slice(s, s + 5),
                    h = g.slice(s + 5, i);
                c = P.PlotUtils.getBezierPoints(c);
                var d = P.PlotUtils.getBezierPoints(h.concat(a.slice(1)));
                u = P.PlotUtils.getBezierPoints(u);
                var f = c.concat(p, d, l, u);
                var newArray = algorithm.array2Dto1D(f);
                result.controlPoint = [o, e, r, this.tempPoint4, this.connPoint];
                result.polygonalPoint = newArray;
            }
            return result.polygonalPoint;
        },
        threeArrow: function (inputPoint) {
            this.connPoint = null;
            this.tempPoint4 = null;
            this.tempPoint5 = null;
            this.points = inputPoint;
            var result = {
                controlPoint: null,
                polygonalPoint: null
            };
            //获取已经点击的坐标数
            var t = inputPoint.length;
            if (t >= 2) {
                if (t == 2) {
                    return inputPoint;
                }
                var o = this.points[0],    //第一个点
                    e = this.points[1],        //第二个点
                    r = this.points[2],        //第三个点
                    t = inputPoint.length; //获取已经点击的坐标数
                //下面的是移动点位后的坐标
                if (t == 3) {
                    this.tempPoint4 = algorithm.getTempPoint4(o, e, r);
                    this.tempPoint5 = P.PlotUtils.mid(r, this.tempPoint4);
                } else {
                    this.tempPoint4 = this.points[3];
                    this.tempPoint5 = this.points[4];
                }
                if (t < 6) {
                    this.connPoint = P.PlotUtils.mid(o, e);
                } else {
                    this.connPoint = this.points[5];
                }
                var n, g;
                if (P.PlotUtils.isClockWise(o, e, r)) {
                    n = algorithm.getArrowPoints(o, this.connPoint, this.tempPoint4, !1);
                    g = algorithm.getArrowPoints(this.connPoint, e, r, !0);
                } else {
                    n = algorithm.getArrowPoints(e, this.connPoint, r, !1);
                    g = algorithm.getArrowPoints(this.connPoint, o, this.tempPoint4, !0);
                }
                var i = n.length,
                    s = (i - 5) / 2,
                    a = n.slice(0, s),
                    l = n.slice(s, s + 5),
                    u = n.slice(s + 5, i),
                    c = g.slice(0, s),
                    p = g.slice(s, s + 5),
                    h = g.slice(s + 5, i);
                c = P.PlotUtils.getBezierPoints(c);
                var d = P.PlotUtils.getBezierPoints(h.concat(a.slice(1)));
                u = P.PlotUtils.getBezierPoints(u);
                var f = c.concat(p, d, l, u);
                var newArray = algorithm.array2Dto1D(f);
                result.controlPoint = [o, e, r, this.tempPoint4, this.tempPoint5, this.connPoint];
                result.polygonalPoint = newArray;
            }
            return result.polygonalPoint;
        },
        array2Dto1D: function (array) {
            var newArray = [];
            array.forEach(function (elt) {
                newArray.push([elt[0], elt[1]]);
            });
            return newArray;
        },
        getArrowPoints: function (t, o, e, r) {
            this.type = doubleArrowDefualParam.type,
                this.headHeightFactor = doubleArrowDefualParam.headHeightFactor,
                this.headWidthFactor = doubleArrowDefualParam.headWidthFactor,
                this.neckHeightFactor = doubleArrowDefualParam.neckHeightFactor,
                this.neckWidthFactor = doubleArrowDefualParam.neckWidthFactor;
            var n = P.PlotUtils.mid(t, o),
                g = P.PlotUtils.distance(n, e),
                i = P.PlotUtils.getThirdPoint(e, n, 0, .3 * g, !0),
                s = P.PlotUtils.getThirdPoint(e, n, 0, .5 * g, !0);
            i = P.PlotUtils.getThirdPoint(n, i, P.Constants.HALF_PI, g / 5, r),
                s = P.PlotUtils.getThirdPoint(n, s, P.Constants.HALF_PI, g / 4, r);
            var a = [n, i, s, e],
                l = algorithm.getArrowHeadPoints(a, this.headHeightFactor, this.headWidthFactor, this.neckHeightFactor, this.neckWidthFactor),
                u = l[0],
                c = l[4],
                p = P.PlotUtils.distance(t, o) / P.PlotUtils.getBaseLength(a) / 2,
                h = algorithm.getArrowBodyPoints(a, u, c, p),
                d = h.length,
                f = h.slice(0, d / 2),
                E = h.slice(d / 2, d);
            return f.push(u),
                E.push(c),
                f = f.reverse(),
                f.push(o),
                E = E.reverse(),
                E.push(t),
                f.reverse().concat(l, E)
        },
        getArrowHeadPoints: function (t, o, e) {
            this.type = doubleArrowDefualParam.type,
                this.headHeightFactor = doubleArrowDefualParam.headHeightFactor,
                this.headWidthFactor = doubleArrowDefualParam.headWidthFactor,
                this.neckHeightFactor = doubleArrowDefualParam.neckHeightFactor,
                this.neckWidthFactor = doubleArrowDefualParam.neckWidthFactor;
            var r = P.PlotUtils.getBaseLength(t),
                n = r * this.headHeightFactor,
                g = t[t.length - 1],
                i = (P.PlotUtils.distance(o, e), n * this.headWidthFactor),
                s = n * this.neckWidthFactor,
                a = n * this.neckHeightFactor,
                l = P.PlotUtils.getThirdPoint(t[t.length - 2], g, 0, n, !0),
                u = P.PlotUtils.getThirdPoint(t[t.length - 2], g, 0, a, !0),
                c = P.PlotUtils.getThirdPoint(g, l, P.Constants.HALF_PI, i, !1),
                p = P.PlotUtils.getThirdPoint(g, l, P.Constants.HALF_PI, i, !0),
                h = P.PlotUtils.getThirdPoint(g, u, P.Constants.HALF_PI, s, !1),
                d = P.PlotUtils.getThirdPoint(g, u, P.Constants.HALF_PI, s, !0);
            return [h, c, g, p, d];
        },
        getArrowBodyPoints: function (t, o, e, r) {
            for (var n = P.PlotUtils.wholeDistance(t), g = P.PlotUtils.getBaseLength(t), i = g * r, s = P.PlotUtils.distance(o, e), a = (i - s) / 2, l = 0, u = [], c = [], p = 1; p < t.length - 1; p++) {
                var h = P.PlotUtils.getAngleOfThreePoints(t[p - 1], t[p], t[p + 1]) / 2;
                l += P.PlotUtils.distance(t[p - 1], t[p]);
                var d = (i / 2 - l / n * a) / Math.sin(h),
                    f = P.PlotUtils.getThirdPoint(t[p - 1], t[p], Math.PI - h, d, !0),
                    E = P.PlotUtils.getThirdPoint(t[p - 1], t[p], h, d, !1);
                u.push(f),
                    c.push(E)
            }
            return u.concat(c)
        },
        getTempPoint4: function (t, o, e) {
            var r, n, g, i, s = P.PlotUtils.mid(t, o),
                a = P.PlotUtils.distance(s, e),
                l = P.PlotUtils.getAngleOfThreePoints(t, s, e);
            return l < P.Constants.HALF_PI ? (n = a * Math.sin(l), g = a * Math.cos(l), i = P.PlotUtils.getThirdPoint(t, s, P.Constants.HALF_PI, n, !1), r = P.PlotUtils.getThirdPoint(s, i, P.Constants.HALF_PI, g, !0)) : l >= P.Constants.HALF_PI && l < Math.PI ? (n = a * Math.sin(Math.PI - l), g = a * Math.cos(Math.PI - l), i = P.PlotUtils.getThirdPoint(t, s, P.Constants.HALF_PI, n, !1), r = P.PlotUtils.getThirdPoint(s, i, P.Constants.HALF_PI, g, !1)) : l >= Math.PI && l < 1.5 * Math.PI ? (n = a * Math.sin(l - Math.PI), g = a * Math.cos(l - Math.PI), i = P.PlotUtils.getThirdPoint(t, s, P.Constants.HALF_PI, n, !0), r = P.PlotUtils.getThirdPoint(s, i, P.Constants.HALF_PI, g, !0)) : (n = a * Math.sin(2 * Math.PI - l), g = a * Math.cos(2 * Math.PI - l), i = P.PlotUtils.getThirdPoint(t, s, P.Constants.HALF_PI, n, !0), r = P.PlotUtils.getThirdPoint(s, i, P.Constants.HALF_PI, g, !1)),
                r
        },
        tailedAttackArrow: function (inputPoint) {
            inputPoint = algorithm.dereplication(inputPoint);
            this.tailWidthFactor = tailedAttackArrowDefualParam.tailWidthFactor;
            this.swallowTailFactor = tailedAttackArrowDefualParam.swallowTailFactor;
            this.swallowTailPnt = tailedAttackArrowDefualParam.swallowTailPnt;
            //控制点
            var result = {
                controlPoint: null,
                polygonalPoint: null
            };
            result.controlPoint = inputPoint;
            var t = inputPoint.length;
            if (!(2 > t)) {
                if (2 == inputPoint.length) {
                    result.polygonalPoint = inputPoint;
                    return result;
                }
                var o = inputPoint,
                    e = o[0],
                    r = o[1];
                P.PlotUtils.isClockWise(o[0], o[1], o[2]) && (e = o[1], r = o[0]);
                var n = P.PlotUtils.mid(e, r),
                    g = [n].concat(o.slice(2)),
                    i = algorithm.getAttackArrowHeadPoints(g, e, r, tailedAttackArrowDefualParam),
                    s = i[0],
                    a = i[4],
                    l = P.PlotUtils.distance(e, r),
                    u = P.PlotUtils.getBaseLength(g),
                    c = u * this.tailWidthFactor * this.swallowTailFactor;
                this.swallowTailPnt = P.PlotUtils.getThirdPoint(g[1], g[0], 0, c, !0);
                var p = l / u,
                    h = algorithm.getAttackArrowBodyPoints(g, s, a, p),
                    t = h.length,
                    d = [e].concat(h.slice(0, t / 2));
                d.push(s);
                var f = [r].concat(h.slice(t / 2, t));
                var newArray = [];
                f.push(a),
                    d = P.PlotUtils.getQBSplinePoints(d),
                    f = P.PlotUtils.getQBSplinePoints(f),
                    newArray = algorithm.array2Dto1D(d.concat(i, f.reverse(), [this.swallowTailPnt, d[0]]));
                result.polygonalPoint = newArray;
            }
            return result;
        },
        getAttackArrowHeadPoints: function (t, o, e, defaultParam) {
            this.headHeightFactor = defaultParam.headHeightFactor;
            this.headTailFactor = defaultParam.headTailFactor;
            this.headWidthFactor = defaultParam.headWidthFactor;
            this.neckWidthFactor = defaultParam.neckWidthFactor;
            this.neckHeightFactor = defaultParam.neckHeightFactor;
            var r = P.PlotUtils.getBaseLength(t),
                n = r * this.headHeightFactor,
                g = t[t.length - 1];
            r = P.PlotUtils.distance(g, t[t.length - 2]);
            var i = P.PlotUtils.distance(o, e);
            n > i * this.headTailFactor && (n = i * this.headTailFactor);
            var s = n * this.headWidthFactor,
                a = n * this.neckWidthFactor;
            n = n > r ? r : n;
            var l = n * this.neckHeightFactor,
                u = P.PlotUtils.getThirdPoint(t[t.length - 2], g, 0, n, !0),
                c = P.PlotUtils.getThirdPoint(t[t.length - 2], g, 0, l, !0),
                p = P.PlotUtils.getThirdPoint(g, u, P.Constants.HALF_PI, s, !1),
                h = P.PlotUtils.getThirdPoint(g, u, P.Constants.HALF_PI, s, !0),
                d = P.PlotUtils.getThirdPoint(g, c, P.Constants.HALF_PI, a, !1),
                f = P.PlotUtils.getThirdPoint(g, c, P.Constants.HALF_PI, a, !0);
            return [d, p, g, h, f]
        },
        getAttackArrowBodyPoints: function (t, o, e, r) {
            for (var n = P.PlotUtils.wholeDistance(t), g = P.PlotUtils.getBaseLength(t), i = g * r, s = P.PlotUtils.distance(o, e), a = (i - s) / 2, l = 0, u = [], c = [], p = 1; p < t.length - 1; p++) {
                var h = P.PlotUtils.getAngleOfThreePoints(t[p - 1], t[p], t[p + 1]) / 2;
                l += P.PlotUtils.distance(t[p - 1], t[p]);
                var d = (i / 2 - l / n * a) / Math.sin(h),
                    f = P.PlotUtils.getThirdPoint(t[p - 1], t[p], Math.PI - h, d, !0),
                    E = P.PlotUtils.getThirdPoint(t[p - 1], t[p], h, d, !1);
                u.push(f),
                    c.push(E)
            }
            return u.concat(c)
        },
        dereplication: function (array) {
            var last = array[array.length - 1];
            var change = false;
            var newArray = [];
            newArray = array.filter(function (i) {
                if (i[0] != last[0] && i[1] != last[1]) {
                    return i;
                }
                change = true;
            });
            if (change) newArray.push(last);
            return newArray;
        },
        fineArrow: function (tailPoint, headerPoint) {
            if ((tailPoint.length < 2) || (headerPoint.length < 2)) return;
            //画箭头的函数
            var tailWidthFactor = fineArrowDefualParam.tailWidthFactor;
            var neckWidthFactor = fineArrowDefualParam.neckWidthFactor;
            var headWidthFactor = fineArrowDefualParam.headWidthFactor;
            var headAngle = fineArrowDefualParam.headAngle;
            var neckAngle = fineArrowDefualParam.neckAngle;
            var o = [];
            o[0] = tailPoint;
            o[1] = headerPoint;
            e = o[0],
                r = o[1],
                n = P.PlotUtils.getBaseLength(o),
                g = n * tailWidthFactor,
                //尾部宽度因子
                i = n * neckWidthFactor,
                //脖子宽度银子
                s = n * headWidthFactor,
                //头部宽度因子
                a = P.PlotUtils.getThirdPoint(r, e, P.Constants.HALF_PI, g, !0),
                l = P.PlotUtils.getThirdPoint(r, e, P.Constants.HALF_PI, g, !1),
                u = P.PlotUtils.getThirdPoint(e, r, headAngle, s, !1),
                c = P.PlotUtils.getThirdPoint(e, r, headAngle, s, !0),
                p = P.PlotUtils.getThirdPoint(e, r, neckAngle, i, !1),
                h = P.PlotUtils.getThirdPoint(e, r, neckAngle, i, !0),
                d = [];
            d.push(a[0], a[1], p[0], p[1], u[0], u[1], r[0], r[1], c[0], c[1], h[0], h[1], l[0], l[1], e[0], e[1]);
            return Cesium.Cartesian3.fromDegreesArray(d);
        }
    }

    let P = {};
    P.PlotUtils = {}, P.PlotUtils.distance = function (t, o) {
        return Math.sqrt(Math.pow(t[0] - o[0], 2) + Math.pow(t[1] - o[1], 2))
    }, P.PlotUtils.wholeDistance = function (t) {
        for (var o = 0, e = 0; e < t.length - 1; e++) o += P.PlotUtils.distance(t[e], t[e + 1]);
        return o
    }, P.PlotUtils.getBaseLength = function (t) {
        return Math.pow(P.PlotUtils.wholeDistance(t), .99)
    }, P.PlotUtils.mid = function (t, o) {
        return [(t[0] + o[0]) / 2, (t[1] + o[1]) / 2]
    }, P.PlotUtils.getCircleCenterOfThreePoints = function (t, o, e) {
        var r = [(t[0] + o[0]) / 2, (t[1] + o[1]) / 2],
            n = [r[0] - t[1] + o[1], r[1] + t[0] - o[0]],
            g = [(t[0] + e[0]) / 2, (t[1] + e[1]) / 2],
            i = [g[0] - t[1] + e[1], g[1] + t[0] - e[0]];
        return P.PlotUtils.getIntersectPoint(r, n, g, i)
    }, P.PlotUtils.getIntersectPoint = function (t, o, e, r) {
        if (t[1] == o[1]) {
            var n = (r[0] - e[0]) / (r[1] - e[1]),
                g = n * (t[1] - e[1]) + e[0],
                i = t[1];
            return [g, i]
        }
        if (e[1] == r[1]) {
            var s = (o[0] - t[0]) / (o[1] - t[1]);
            return g = s * (e[1] - t[1]) + t[0], i = e[1], [g, i]
        }
        return s = (o[0] - t[0]) / (o[1] - t[1]), n = (r[0] - e[0]) / (r[1] - e[1]), i = (s * t[1] - t[0] - n * e[1] + e[0]) / (s - n), g = s * i - s * t[1] + t[0], [g, i]
    }, P.PlotUtils.getAzimuth = function (t, o) {
        var e, r = Math.asin(Math.abs(o[1] - t[1]) / P.PlotUtils.distance(t, o));
        return o[1] >= t[1] && o[0] >= t[0] ? e = r + Math.PI : o[1] >= t[1] && o[0] < t[0] ? e = P.Constants.TWO_PI - r : o[1] < t[1] && o[0] < t[0] ? e = r : o[1] < t[1] && o[0] >= t[0] && (e = Math.PI - r), e
    }, P.PlotUtils.getAngleOfThreePoints = function (t, o, e) {
        var r = P.PlotUtils.getAzimuth(o, t) - P.PlotUtils.getAzimuth(o, e);
        return 0 > r ? r + P.Constants.TWO_PI : r
    }, P.PlotUtils.isClockWise = function (t, o, e) {
        return (e[1] - t[1]) * (o[0] - t[0]) > (o[1] - t[1]) * (e[0] - t[0])
    }, P.PlotUtils.getPointOnLine = function (t, o, e) {
        var r = o[0] + t * (e[0] - o[0]),
            n = o[1] + t * (e[1] - o[1]);
        return [r, n]
    }, P.PlotUtils.getCubicValue = function (t, o, e, r, n) {
        t = Math.max(Math.min(t, 1), 0);
        var g = 1 - t,
            i = t * t,
            s = i * t,
            a = g * g,
            l = a * g,
            u = l * o[0] + 3 * a * t * e[0] + 3 * g * i * r[0] + s * n[0],
            c = l * o[1] + 3 * a * t * e[1] + 3 * g * i * r[1] + s * n[1];
        return [u, c]
    }, P.PlotUtils.getThirdPoint = function (t, o, e, r, n) {
        var g = P.PlotUtils.getAzimuth(t, o),
            i = n ? g + e : g - e,
            s = r * Math.cos(i),
            a = r * Math.sin(i);
        return [o[0] + s, o[1] + a]
    }, P.PlotUtils.getArcPoints = function (t, o, e, r) {
        var n, g, i = [],
            s = r - e;
        s = 0 > s ? s + P.Constants.TWO_PI : s;
        for (var a = 0; a <= P.Constants.FITTING_COUNT; a++) {
            var l = e + s * a / P.Constants.FITTING_COUNT;
            n = t[0] + o * Math.cos(l), g = t[1] + o * Math.sin(l), i.push([n, g])
        }
        return i
    }, P.PlotUtils.getBisectorNormals = function (t, o, e, r) {
        var n = P.PlotUtils.getNormal(o, e, r),
            g = Math.sqrt(n[0] * n[0] + n[1] * n[1]),
            i = n[0] / g,
            s = n[1] / g,
            a = P.PlotUtils.distance(o, e),
            l = P.PlotUtils.distance(e, r);
        if (g > P.Constants.ZERO_TOLERANCE) if (P.PlotUtils.isClockWise(o, e, r)) {
            var u = t * a,
                c = e[0] - u * s,
                p = e[1] + u * i,
                h = [c, p];
            u = t * l, c = e[0] + u * s, p = e[1] - u * i;
            var d = [c, p]
        } else u = t * a, c = e[0] + u * s, p = e[1] - u * i, h = [c, p], u = t * l, c = e[0] - u * s, p = e[1] + u * i, d = [c, p];
        else c = e[0] + t * (o[0] - e[0]), p = e[1] + t * (o[1] - e[1]), h = [c, p], c = e[0] + t * (r[0] - e[0]), p = e[1] + t * (r[1] - e[1]), d = [c, p];
        return [h, d]
    }, P.PlotUtils.getNormal = function (t, o, e) {
        var r = t[0] - o[0],
            n = t[1] - o[1],
            g = Math.sqrt(r * r + n * n);
        r /= g, n /= g;
        var i = e[0] - o[0],
            s = e[1] - o[1],
            a = Math.sqrt(i * i + s * s);
        i /= a, s /= a;
        var l = r + i,
            u = n + s;
        return [l, u]
    }, P.PlotUtils.getCurvePoints = function (t, o) {
        for (var e = P.PlotUtils.getLeftMostControlPoint(o), r = [e], n = 0; n < o.length - 2; n++) {
            var g = o[n],
                i = o[n + 1],
                s = o[n + 2],
                a = P.PlotUtils.getBisectorNormals(t, g, i, s);
            r = r.concat(a)
        }
        var l = P.PlotUtils.getRightMostControlPoint(o);
        r.push(l);
        var u = [];
        for (n = 0; n < o.length - 1; n++) {
            g = o[n], i = o[n + 1], u.push(g);
            for (var t = 0; t < P.Constants.FITTING_COUNT; t++) {
                var c = P.PlotUtils.getCubicValue(t / P.Constants.FITTING_COUNT, g, r[2 * n], r[2 * n + 1], i);
                u.push(c)
            }
            u.push(i)
        }
        return u
    }, P.PlotUtils.getLeftMostControlPoint = function (o) {
        var e = o[0],
            r = o[1],
            n = o[2],
            g = P.PlotUtils.getBisectorNormals(0, e, r, n),
            i = g[0],
            s = P.PlotUtils.getNormal(e, r, n),
            a = Math.sqrt(s[0] * s[0] + s[1] * s[1]);
        if (a > P.Constants.ZERO_TOLERANCE) var l = P.PlotUtils.mid(e, r),
            u = e[0] - l[0],
            c = e[1] - l[1],
            p = P.PlotUtils.distance(e, r),
            h = 2 / p,
            d = -h * c,
            f = h * u,
            E = d * d - f * f,
            v = 2 * d * f,
            A = f * f - d * d,
            _ = i[0] - l[0],
            y = i[1] - l[1],
            m = l[0] + E * _ + v * y,
            O = l[1] + v * _ + A * y;
        else m = e[0] + t * (r[0] - e[0]), O = e[1] + t * (r[1] - e[1]);
        return [m, O]
    }, P.PlotUtils.getRightMostControlPoint = function (o) {
        var e = o.length,
            r = o[e - 3],
            n = o[e - 2],
            g = o[e - 1],
            i = P.PlotUtils.getBisectorNormals(0, r, n, g),
            s = i[1],
            a = P.PlotUtils.getNormal(r, n, g),
            l = Math.sqrt(a[0] * a[0] + a[1] * a[1]);
        if (l > P.Constants.ZERO_TOLERANCE) var u = P.PlotUtils.mid(n, g),
            c = g[0] - u[0],
            p = g[1] - u[1],
            h = P.PlotUtils.distance(n, g),
            d = 2 / h,
            f = -d * p,
            E = d * c,
            v = f * f - E * E,
            A = 2 * f * E,
            _ = E * E - f * f,
            y = s[0] - u[0],
            m = s[1] - u[1],
            O = u[0] + v * y + A * m,
            T = u[1] + A * y + _ * m;
        else O = g[0] + t * (n[0] - g[0]), T = g[1] + t * (n[1] - g[1]);
        return [O, T]
    }, P.PlotUtils.getBezierPoints = function (t) {
        if (t.length <= 2) return t;
        for (var o = [], e = t.length - 1, r = 0; 1 >= r; r += .01) {
            for (var n = 0, y = 0, g = 0; e >= g; g++) {
                var i = P.PlotUtils.getBinomialFactor(e, g),
                    s = Math.pow(r, g),
                    a = Math.pow(1 - r, e - g);
                n += i * s * a * t[g][0], y += i * s * a * t[g][1]
            }
            o.push([n, y])
        }
        return o.push(t[e]), o
    }, P.PlotUtils.getBinomialFactor = function (t, o) {
        return P.PlotUtils.getFactorial(t) / (P.PlotUtils.getFactorial(o) * P.PlotUtils.getFactorial(t - o))
    }, P.PlotUtils.getFactorial = function (t) {
        if (1 >= t) return 1;
        if (2 == t) return 2;
        if (3 == t) return 6;
        if (4 == t) return 24;
        if (5 == t) return 120;
        for (var o = 1, e = 1; t >= e; e++) o *= e;
        return o
    }, P.PlotUtils.getQBSplinePoints = function (t) {
        if (t.length <= 2) return t;
        var o = 2,
            e = [],
            r = t.length - o - 1;
        e.push(t[0]);
        for (var n = 0; r >= n; n++) for (var g = 0; 1 >= g; g += .05) {
            for (var i = y = 0, s = 0; o >= s; s++) {
                var a = P.PlotUtils.getQuadricBSplineFactor(s, g);
                i += a * t[n + s][0], y += a * t[n + s][1]
            }
            e.push([i, y])
        }
        return e.push(t[t.length - 1]), e
    }, P.PlotUtils.getQuadricBSplineFactor = function (t, o) {
        return 0 == t ? Math.pow(o - 1, 2) / 2 : 1 == t ? (-2 * Math.pow(o, 2) + 2 * o + 1) / 2 : 2 == t ? Math.pow(o, 2) / 2 : 0
    }, P.Constants = {
        TWO_PI: 2 * Math.PI,
        HALF_PI: Math.PI / 2,
        FITTING_COUNT: 100,
        ZERO_TOLERANCE: 1e-4
    }

    /**
     * 结束绘制
     */
    _.prototype.end = function () {
        this.draw && this._map.removeInteraction(this.draw);
        this.draw = undefined;
    }

    /**
     * 暂停/继续绘制
     */
    _.prototype.pause = function () {
        this.draw && this.draw.setActive(!this.draw.getActive());
    }

    /**
    * 清除
    */
    _.prototype.clear = function () {
        this.draw && this._map.removeInteraction(this.draw);
        this._map.removeLayer(this.vector);
        this.draw = undefined;
        this.vector = undefined;
    }

    return _;
});
/**
 *
 *      实现功能：添加wfs服务。
 *      
 *      创建人员：薛鹏
 *
 *      创建日期：2020-03-17
 *
 *      参与人员：薛鹏、张丹钊
 *
 *      最后修改人员：薛鹏
 *
 *      最后修改时间：2020-03-17
 *
 * */
define('SGWorld/Creator/WfsFeatureLayer',['../Core/Core'], function (Core) {
    'use strict';
    /**
    *
    * 这个方法用于添加wfs服务。
    *
    * @alias addLayer 
    * @constructor
    *
    */
    function _(map) {
        this._map = map;
        this._core = new Core();
    }

    /**
    * 这个方法用于添加WFS服务图层
    *@param {String} [name] 名称
    *@param {String} [urlOrSource] url或source。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    _.prototype.createWFSLayer = function (name, urlOrSource, option, callback) {
        let layerOption;
        !option && (option = {});
        let _this = this;
        if (typeof urlOrSource === 'string') {
            !option.projection && (option.projection = 'EPSG:4326');
            layerOption = {
                source: new ol.source.Vector({
                    format: new ol.format.GeoJSON(),
                    url: function (extent) {
                        return urlOrSource + '?service=WFS&version=' + _this._core.defaultValue(option.version, '1.1.0') +
                            '&request=GetFeature&typename=' + option.layer +
                            '&outputFormat=application/json' + '&srsname=' + option.projection + '&' +
                            'bbox=' + extent.join(',') + ',' + option.projection;
                    },
                    strategy: ol.loadingstrategy.bbox
                })
            }
        } else if (typeof urlOrSource === 'object') {
            layerOption = {
                source: urlOrSource
            }
        } else {
            layerOption = {};
        }

        layerOption = this._core.extend(layerOption, option, true);

        if (!layerOption.style) {
            let style = {};
            if (layerOption.fillColor) {
                style.fill = new ol.style.Fill({
                    color: layerOption.fillColor
                });
            }
            if (layerOption.lineColor || layerOption.width) {
                style.stroke = new ol.style.Stroke({
                    color: this._core.defaultValue(layerOption.lineColor, 'rgba(0, 0, 255, 1.0)'),
                    width: this._core.defaultValue(layerOption.width, 2)
                });
            }
            if (layerOption.textColor || layerOption.textScale) {
                style.text = new ol.style.Text({
                    fill: this._core.defaultValue(layerOption.textColor, '#333'),
                    scale: this._core.defaultValue(layerOption.textScale, 1)
                });
            }
            if (style.fill || style.stroke || style.text) {
                layerOption.style = new ol.style.Style(style);
            }
        }
        name && (layerOption.className = name);
        let layer = new ol.layer.Vector(layerOption);

        this._map.addLayer(layer);

        return layer;
    }

    /**
    * 这个方法用于添加GeoJSON图层
    *@param {String} [name] 名称
    *@param {String} [urlOrSource] url或source。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    _.prototype.createGeoJSONLayer = function (name, urlOrSource, option, callback) {
        let layerOption;
        !option && (option = {});
        if (typeof urlOrSource === 'string') {
            !option.projection && (option.projection = 'EPSG:4326');
            layerOption = {
                source: new ol.source.Vector({
                    format: new ol.format.GeoJSON(),
                    url: function (extent) {
                        return urlOrSource + '&srsname=' + option.projection + '&' +
                            'bbox=' + extent.join(',') + ',' + option.projection;
                    },
                    strategy: ol.loadingstrategy.bbox
                })
            }
        } else if (typeof urlOrSource === 'object') {
            layerOption = {
                source: urlOrSource
            }
        } else {
            layerOption = {};
        }

        layerOption = this._core.extend(layerOption, option, true);

        if (!layerOption.style) {
            let style = {};
            if (layerOption.fillColor) {
                style.fill = new ol.style.Fill({
                    color: layerOption.fillColor
                });
            }
            if (layerOption.lineColor || layerOption.width) {
                style.stroke = new ol.style.Stroke({
                    color: this._core.defaultValue(layerOption.lineColor, 'rgba(0, 0, 255, 1.0)'),
                    width: this._core.defaultValue(layerOption.width, 2)
                });
            }
            if (layerOption.textColor || layerOption.textScale) {
                style.text = new ol.style.Text({
                    fill: this._core.defaultValue(layerOption.textColor, '#333'),
                    scale: this._core.defaultValue(layerOption.textScale, 1)
                });
            }
            if (style.fill || style.stroke || style.text) {
                layerOption.style = new ol.style.Style(style);
            }
        }
        name && (layerOption.className = name);
        let layer = new ol.layer.Vector(layerOption);

        this._map.addLayer(layer);

        return layer;
    }

    /**
    * 这个方法用于添加GeoJSON文件
    *@param {String} [name] 名称
    *@param {String} [urlOrSource] url或source。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    _.prototype.addGeoJSONFile = function (name, urlOrSource, option, callback) {
        let layerOption;
        !option && (option = {});
        if (typeof urlOrSource === 'string') {
            !option.projection && (option.projection = 'EPSG:4326');
            layerOption = {
                source: new ol.source.Vector({
                    format: new ol.format.GeoJSON(),
                    url: urlOrSource
                })
            }
        } else if (typeof urlOrSource === 'object') {
            layerOption = {
                source: urlOrSource
            }
        } else {
            layerOption = {};
        }

        layerOption = this._core.extend(layerOption, option, true);

        if (!layerOption.style) {
            let style = {};
            if (layerOption.fillColor) {
                style.fill = new ol.style.Fill({
                    color: layerOption.fillColor
                });
            }
            if (layerOption.lineColor || layerOption.width) {
                style.stroke = new ol.style.Stroke({
                    color: this._core.defaultValue(layerOption.lineColor, 'rgba(0, 0, 255, 1.0)'),
                    width: this._core.defaultValue(layerOption.width, 2)
                });
            }
            if (layerOption.text || layerOption.textColor || layerOption.textScale) {
                style.text = new ol.style.Text({
                    text: this._core.defaultValue(layerOption.text, '新建文本'),
                    fill: this._core.defaultValue(layerOption.textColor, '#333'),
                    scale: this._core.defaultValue(layerOption.textScale, 1)
                });
            }
            if (layerOption.image) {
                style.image = new ol.style.Icon({
                    src: layerOption.image,
                    scale: this._core.defaultValue(layerOption.imageScale, 1)
                });
            }
            if (style.fill || style.stroke || style.text || style.image) {
                layerOption.style = new ol.style.Style(style);
            }
        }
        name && (layerOption.className = name);
        let layer = new ol.layer.Vector(layerOption);

        this._map.addLayer(layer);

        return layer;
    }

    return _;
});
/**
 *
 *      实现功能：添加wms服务。
 *      
 *      创建人员：薛鹏
 *
 *      创建日期：2020-03-17
 *
 *      参与人员：薛鹏、张丹钊
 *
 *      最后修改人员：薛鹏
 *
 *      最后修改时间：2020-03-17
 *
 * */
define('SGWorld/Creator/WmsFeatureLayer',['../Core/Core'], function (Core) {
    'use strict';
    /**
    *
    * 这个方法用于添加wfs服务。
    *
    * @alias addLayer 
    * @constructor
    *
    */
    function _(map) {
        this._map = map;
        this._core = new Core();
    }

    /**
    * 这个方法用于添加WMS服务图层
    *@param {String} [name] 名称
    *@param {String} [urlOrSource] url或source。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    _.prototype.createWMSLayer = function (name, urlOrSource, option, callback) {
        let layerOption;
        !option && (option = {});
        if (typeof urlOrSource === 'string') {
            layerOption = {
                extent: option.extent || [-180, -90, 180, 90],
                source: new ol.source.ImageWMS({
                    url: urlOrSource,
                    params: { 'LAYERS': option.layer },
                    ratio: this._core.defaultValue(option.ratio, 1),
                    serverType: option.serverType
                })
            }
        } else if (typeof urlOrSource === 'object') {
            layerOption = {
                source: urlOrSource
            }
        } else {
            layerOption = {};
        }

        layerOption = this._core.extend(layerOption, option, true);
        name && (layerOption.className = name);
        let layer = new ol.layer.Image(layerOption);

        this._map.addLayer(layer);

        return layer;
    }

    return _;
});
/**
 *
 *      实现功能：添加wmts服务。
 *      
 *      创建人员：薛鹏
 *
 *      创建日期：2020-03-17
 *
 *      参与人员：薛鹏、张丹钊
 *
 *      最后修改人员：薛鹏
 *
 *      最后修改时间：2020-03-17
 *
 * */
define('SGWorld/Creator/WmtsFeatureLayer',['../Core/Core'], function (Core) {
    'use strict';
    /**
    *
    * 这个方法用于添加Wmts服务。
    *
    * @alias createWMTSLayer 
    * @constructor
    *
    */
    function _(map) {
        this._map = map;
        this._core = new Core();
    }

    /**
    * 这个方法用于添加WMTS服务图层
    *@param {String} [name] 名称
    *@param {String} [urlOrSource] url或source。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    _.prototype.createWMTSLayer = function (name, urlOrSource, option, callback) {
        let layerOption;
        !option && (option = {});
        if (typeof urlOrSource === 'string') {
            !option.projection && (option.projection = 'EPSG:4326');
            if (option.projection === 'EPSG:4490') this._core.addEPSG('EPSG:4490');
            let projection = ol.proj.get(option.projection);
            let projectionExtent = projection.getExtent();
            let size = ol.extent.getWidth(projectionExtent) / 256;

            let resolutions = projection.resolutions;
            let matrixIds = projection.matrixIds;
            if (!resolutions || !matrixIds) {
                resolutions = new Array(14);
                matrixIds = new Array(14);
                for (let z = 0; z < 14; ++z) {
                    // generate resolutions and matrixIds arrays for this WMTS
                    resolutions[z] = size / Math.pow(2, z);
                    matrixIds[z] = z;
                }
            }

            layerOption = {
                opacity: 0.7,
                source: new ol.source.WMTS({
                    attributions: 'Tiles © <a href="' + urlOrSource + '>wmts</a>',
                    url: urlOrSource,
                    layer: option.layer || '0',
                    matrixSet: option.projection,
                    format: option.format || 'image/png',
                    projection: projection,
                    tileGrid: new ol.tilegrid.WMTS({
                        origin: ol.extent.getTopLeft(projectionExtent),
                        resolutions: resolutions,
                        matrixIds: matrixIds
                    }),
                    style: option.style === undefined ? 'default' : option.style,
                    wrapX: option.wrapX === undefined ? true : option.wrapX
                })
            }
        } else if (typeof urlOrSource === 'object') {
            layerOption = {
                source: urlOrSource
            }
        } else {
            layerOption = {};
        }

        layerOption = this._core.extend(layerOption, option, true);
        name && (layerOption.className = name);
        let layer = new ol.layer.Tile(layerOption);

        this._map.addLayer(layer);

        return layer;
    }
    return _;
});
/**
 *
 *      实现功能：创建测量。
 *      
 *      创建人员：张丹钊
 *
 *      创建日期：2020-03-19
 *
 *      参与人员：张丹钊
 *
 *      最后修改人员：张丹钊
 *
 *      最后修改时间：2020-03-19
 *
 * */
define('SGWorld/Creator/Measure',['../Core/Core'], function (Core) {
    'use strict';
    /**
    *
    * 这个方法用于创建线。
    *
    * @alias addLayer 
    * @constructor
    *
    */
    function _(map) {
        this._map = map;
        this._core = new Core();
        this.draw = undefined;
        this.vector = undefined;
        this.result = [];
    }

    var sketch;  //当前绘制要素
    var tooltip, resultTooltip;  //提示

    /**
    * 这个方法用于创建测量
    *@param {String} [type] 测量类型（distance/area）。
    * @param {Object} [option] 参数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    _.prototype.createMeasure = function (type, option) {

        if (!this.vector) {
            this.source = new ol.source.Vector();
            this.vector = new ol.layer.Vector({
                source: this.source,
                style: new ol.style.Style({
                    fill: new ol.style.Fill({
                        color: 'rgba(255, 255, 255, 0.2)'
                    }),
                    stroke: new ol.style.Stroke({
                        color: '#ffcc33',
                        width: 2
                    }),
                    image: new ol.style.Circle({
                        radius: 7,
                        fill: new ol.style.Fill({
                            color: '#ffcc33'
                        })
                    })
                })
            });
            this._map.addLayer(this.vector);

            this._map.getViewport().addEventListener('mouseout', mouseout);
            this._map.on('pointermove', pointerMoveHandler);
        }

        !tooltip && (tooltip = this._core.createHelpTooltip(this._map));

        this.startMeasure(type, option);

        return this;
    }

    /**
    * 执行测量
    *@param {String} [type] 测量类型（distance/area）。
    * @param {Object} [option] 参数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    _.prototype.startMeasure = function (type, option) {
        type = (type == 'area' ? 'Polygon' : 'LineString');
        this.draw && this._map.removeInteraction(this.draw);

        this.draw = new ol.interaction.Draw({
            source: this.source,
            type: type,
            style: new ol.style.Style({
                fill: new ol.style.Fill({
                    color: 'rgba(255, 255, 255, 0.2)'
                }),
                stroke: new ol.style.Stroke({
                    color: 'rgba(0, 0, 0, 0.5)',
                    lineDash: [10, 10],
                    width: 2
                }),
                image: new ol.style.Circle({
                    radius: 5,
                    stroke: new ol.style.Stroke({
                        color: 'rgba(0, 0, 0, 0.7)'
                    }),
                    fill: new ol.style.Fill({
                        color: 'rgba(255, 255, 255, 0.2)'
                    })
                })
            })
        });

        this._map.addInteraction(this.draw);

        resultTooltip = this._core.createResultTooltip(this._map);
        this.result.push(resultTooltip);

        var listener;
        var _this = this;
        this.draw.on('drawstart',
            function (evt) {
                // set sketch
                sketch = evt.feature;

                var tooltipCoord = evt.coordinate;

                listener = sketch.getGeometry().on('change', function (evt) {
                    var geom = evt.target;
                    var output;
                    if (geom instanceof ol.geom.Polygon) {
                        output = _this.formatArea(geom);
                        tooltipCoord = geom.getInteriorPoint().getCoordinates();
                    } else if (geom instanceof ol.geom.LineString) {
                        output = _this.formatLength(geom);
                        tooltipCoord = geom.getLastCoordinate();
                    }
                    resultTooltip && resultTooltip.showAt(output, tooltipCoord);
                });
            });

        this.draw.on('drawend',
            function () {
                resultTooltip.static(true);

                sketch = null;
                resultTooltip = null;
                resultTooltip = _this._core.createResultTooltip(_this._map);
                _this.result.push(resultTooltip);

                ol.Observable.unByKey(listener);
            });
    }

    /**
    * 结束测量
    */
    _.prototype.end = function () {
        this.draw && this._map.removeInteraction(this.draw);
        this.draw = undefined;
    }

    /**
     * 暂停/继续绘制
     */
    _.prototype.pause = function () {
        this.draw && this.draw.setActive(!this.draw.getActive());
    }

    /**
    * 清除测量
    */
    _.prototype.clear = function () {
        this.draw && this._map.removeInteraction(this.draw);
        this._map.removeLayer(this.vector);
        this.draw = undefined;
        this.vector = undefined;
    }

    //鼠标移出
    function mouseout() {
        tooltip && tooltip.show(false);
    }

    //鼠标移动
    function pointerMoveHandler(evt) {
        if (evt.dragging) {
            return;
        }
        /** @type {string} */
        var helpMsg = '点击开始绘制';

        sketch && (helpMsg = '双击结束绘制');

        tooltip && tooltip.showAt(helpMsg, evt.coordinate);
        tooltip.show(true);
    };

    /**
     * 计算线长度.
     *@param {Line} [line] 线。
     * @return {string} [output] 长度.
     */
    _.prototype.formatLength = function (line) {
        var length = ol.sphere.getLength(line);
        var output;
        if (length > 100) {
            output = (Math.round(length / 1000 * 100) / 100) +
                ' ' + 'km';
        } else {
            output = (Math.round(length * 100) / 100) +
                ' ' + 'm';
        }
        return output;
    };


    /**
     * 计算面积.
     * @param {Polygon} [polygon] 面.
     * @return {string} [output] 面积.
     */
    _.prototype.formatArea = function (polygon) {
        var area = ol.sphere.getArea(polygon);
        var output;
        if (area > 10000) {
            output = (Math.round(area / 1000000 * 100) / 100) +
                ' ' + 'km<sup>2</sup>';
        } else {
            output = (Math.round(area * 100) / 100) +
                ' ' + 'm<sup>2</sup>';
        }
        return output;
    };

    return _;
});
define('SGWorld/Creator/Creator',[
    "../Core/Core",
    "./Color",
    "./Layer",
    "./Point",
    "./Polyline",
    "./Polygon",
    "./Circle",
    "./Rectangle",
    "./Star",
    "./MilitaryObject",
    "./WfsFeatureLayer",
    "./WmsFeatureLayer",
    "./WmtsFeatureLayer",
    "./Measure"
], function (
    core,
    Color,
    Layer,
    Point,
    Polyline,
    Polygon,
    Circle,
    Rectangle,
    Star,
    MilitaryObject,
    WfsFeatureLayer,
    WmsFeatureLayer,
    WmtsFeatureLayer,
    Measure
) {
    'use strict';

    /**
     *
     * 创建模块。
     *
     * @alias Creator
     * @constructor
     *
     */
    function Creator(map) {
        this._map = map;
        this._core = new core();
        this._Color = new Color();
        //图层
        this._Layer = new Layer(map);
        //点
        this._Point = new Point(map);
        //线
        this._Polyline = new Polyline(map);
        //面
        this._Polygon = new Polygon(map);
        //圆
        this._Circle = new Circle(map);
        //矩形
        this._Rectangle = new Rectangle(map);
        //星
        this._Star = new Star(map);
        //wfs
        this._WfsFeatureLayer = new WfsFeatureLayer(map);
        //wms
        this._WmsFeatureLayer = new WmsFeatureLayer(map);
        //wmts
        this._WmtsFeatureLayer = new WmtsFeatureLayer(map);
        //测量
        this._Measure = new Measure(map);
    };

    /**
    * 这个方法用于添加div点对象
    * @param {Array} [position] 位置
    * @param {Object} [option] 点参数。
    * 
    */
    Creator.prototype.addDivPoint = function (position, option) {
        return this._Point.addDivPoint(position, option);
    }
    /**
     * 创建点
     */
    Creator.prototype.CreatePoint = function (option) {
        let _Point = new Point(this._map);
        return _Point.createPoint(option);
    }
    /**
    * 创建线
    */
    Creator.prototype.CreatePolyline = function (option) {
        let _Polyline = new Polyline(this._map);
        return _Polyline.createPolyline(option);
    }
    /**
     * 创建面
     */
    Creator.prototype.CreatePolygon = function (option) {
        let _Polygon = new Polygon(this._map);
        return _Polygon.createPolygon(option);
    }

    /**
    * 创建圆
    */
    Creator.prototype.CreateCircle = function (option) {
        return this._Circle.createCircle(option);
    }

    /**
    * 创建矩形
    * @param {Object} [option] 图层参数。
    */
    Creator.prototype.CreateRectangle = function (option) {
        let _rectangle = new Rectangle(this._map);
        return _rectangle.createRectangle(option);
    }

    /**
    * 创建正方形
    * @param {Object} [option] 图层参数。
    */
    Creator.prototype.CreateSquare = function (option) {
        let _square = new Rectangle(this._map);
        return _square.createSquare(option);
    }

    /**
    * 创建星形
    * @param {Object} [option] 图层参数。
    */
    Creator.prototype.CreateStar = function (option) {
        return this._Star.createStar(option);
    }

    /**
    * 创建军事标绘
    * @param {String} [type] 军标类型。
    * @param {Object} [option] 图层参数。
    */
    Creator.prototype.CreateMilitaryObject = function (type, option) {
        let _militaryObject = new MilitaryObject(this._map);
        return _militaryObject.createMilitaryObject(type, option);
    }

    /**
    * 这个方法用于添加GeoJSON图层
    *@param {String} [name] 名称
    *@param {String} [urlOrSource] url或source。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    Creator.prototype.CreateGeoJSONLayer = function (name, urlOrSource, option, callback) {
        return this._WfsFeatureLayer.createGeoJSONLayer(name, urlOrSource, option, callback);
    }

    /**
    * 这个方法用于添加GeoJSON文件
    *@param {String} [name] 名称
    *@param {String} [urlOrSource] url或source。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    Creator.prototype.AddGeoJSONFile = function (name, urlOrSource, option, callback) {
        return this._WfsFeatureLayer.addGeoJSONFile(name, urlOrSource, option, callback);
    }

    /**
    * 这个方法用于添加WFS服务图层
    *@param {String} [name] 名称
    *@param {String} [urlOrSource] url或source。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    Creator.prototype.CreateWFSLayer = function (name, urlOrSource, option, callback) {
        return this._WfsFeatureLayer.createWFSLayer(name, urlOrSource, option, callback);
    }

    /**
    * 这个方法用于添加WMS服务图层
    *@param {String} [name] 名称
    *@param {String} [urlOrSource] url或source。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    Creator.prototype.CreateWMSLayer = function (name, urlOrSource, option, callback) {
        return this._WmsFeatureLayer.createWMSLayer(name, urlOrSource, option, callback);
    }

    /**
    * 这个方法用于添加WMTS服务图层
    *@param {String} [name] 名称
    *@param {String} [urlOrSource] url或source。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    Creator.prototype.CreateWMTSLayer = function (name, urlOrSource, option, callback) {
        return this._WmtsFeatureLayer.createWMTSLayer(name, urlOrSource, option, callback);
    }
    /**
    * 这个方法用于添加切片图层
    *@param {String} [name] 名称
    *@param {String} [urlOrSource] url或source。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    Creator.prototype.addTileLayer = function (name, urlOrSource, option, callback) {
        return this._Layer.addTileLayer(name, urlOrSource, option, callback);
    }

    /**
    * 这个方法用于添加影像图层
    *@param {String} [name] 名称
    *@param {String} [urlOrSource] url或source。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    Creator.prototype.addImageLayer = function (name, urlOrSource, option, callback) {
        return this._Layer.addImageLayer(name, urlOrSource, option, callback);
    }

    /**
    * 这个方法用于添加ArcGISRest服务
    *@param {String} [name] 名称
    *@param {String} [urlOrSource] url或source。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    Creator.prototype.TileArcGISRest = function (name, urlOrSource, option, callback) {
        return this._Layer.TileArcGISRest(name, urlOrSource, option, callback);
    }

    /**
    * 这个方法用于添加ArcGISRest影像服务
    *@param {String} [name] 名称
    *@param {String} [urlOrSource] url或source。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    Creator.prototype.ImageArcGISRest = function (name, urlOrSource, option, callback) {
        return this._Layer.ImageArcGISRest(name, urlOrSource, option, callback);
    }

    /**
    * 这个方法用于添加FeatureService服务
    *@param {String} [name] 名称
    *@param {String} [urlOrSource] url或source。
    * @param {Object} [option] 图层参数。
    * @param {Function} [callback] 回调函数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    Creator.prototype.CreateFeatureService = function (name, urlOrSource, option, callback) {
        return this._Layer.FeatureService(name, urlOrSource, option, callback);
    }

    /**
    * 这个方法用于创建测量
    *@param {String} [type] 测量类型（distance/area）。
    * @param {Object} [option] 参数。
    * @returns {Promise.<Object>} 返回一个Openlayer的图层对象。
    */
    Creator.prototype.createMeasure = function (type, option) {
        return this._Measure.createMeasure(type, option);
    }
    return Creator;
});
/**
 *
 *      实现功能：这个方法用于激活标准菜单命令.
 *
 *      创建人员：薛鹏
 *
 *      创建日期：2019-03-13
 *
 *      参与人员：金磊
 *
 *      最后修改人员：金磊
 *
 *      最后修改时间：2019-03-13
 *
 * */
define('SGWorld/Command/execute',[
    '../Core/Core'
], function (
    Core
) {
    'use strict';

    function _() {
        this._core = new Core();
        this._polyline = undefined; 
        this._polygon = undefined;
    }

    /**
     * 这个方法用于激活标准菜单命令，完整的功能调用。
     *@param {int} [commandid] 菜单命令id,其中(0,.)为创建模块、(1..)为分析模块。
     *@param {int} [parameters] 菜单命令id。
     *@param {Object} [parameter] 参数。
     *@param {function} [method] 回调。
     *
     */
    _.prototype.execute = function (commandid, parameters, parameter, method) {
        var core = this._core;
        if (commandid == 0 && parameters == 0) {
            return this._point;
        } 
    }
    return _;
});
define('SGWorld/Command/Command',["./execute"], function (execute) {
    'use strict';
    function Command() {
        this._execute = new execute();

    };
    Command.prototype.execute = function (commandid, parameters, parameter, method) {
        return this._execute.execute(commandid, parameters, parameter, method);
    }

    return Command;
});
/**
 *
 *      实现功能：缓冲区分析。
 *
 *      创建人员：张丹钊
 *
 *      创建日期：2020-04-29
 *
 *      参与人员：张丹钊
 *
 *      最后修改人员：张丹钊
 *
 *      最后修改时间：2020-04-29
 *
 * */
define('SGWorld/Analysis/BufferAnalysis',["../Core/Core"], function (core) {
    'use strict';

    /**
     *
     * 缓冲区分析。
     *
     * @alias BufferAnalysis
     * @constructor
     *
     */
    function _(map) {
        this._map = map;
        this._core = new core();
    }

    /**
     * 设置缓冲区大小
     * @param {Number} [value] 半径，米
     *
     */
    _.prototype.changeBurr = function (value) {
        this.num = value;
        if (this.source) {
            switch (this.type) {
                case 'point':
                    this.setPointBuff(this.num);
                    break;
                case 'polyline':
                    this.setPolylineBuff(this.num);
                    break;
                case 'polygon':
                    this.setPolygonBuff(this.num);
                    break;
            }
        }
    }

    /**
     * 画点
     *
     */
    _.prototype.DrawPoint = function (num, callback) {
        this.type = 'point';
        this.source = new ol.source.Vector();
        this.vector = new ol.layer.Vector({
            source: this.source,
            style: new ol.style.Style({
                fill: new ol.style.Fill({
                    color: 'rgba(255, 0, 0, 0.3)'
                }),
                stroke: new ol.style.Stroke({
                    color: '#ffcc33',
                    width: 2
                })
            })
        });
        this._map.addLayer(this.vector);

        let _this = this;
        let position;
        this.draw = new ol.interaction.Draw({
            source: this.source,
            type: "Point",
            geometryFunction: function (coordinates, geometry) {
                if (!geometry) {
                    //根据绘制的坐标返回自定义的geometry，随意拓展 
                    position = coordinates;
                    geometry = new ol.geom.Circle(coordinates, _this._core.defaultValue(num, 100));
                }
                return geometry;
            }
        });

        // this.draw.on('drawstart',
        //     function (evt) {

        //     });


        this.draw.on('drawend',
            function () {
                callback && typeof callback === 'function' && callback(position);
                _this.stop();
            });

        this._map.addInteraction(this.draw);
        return this;
    }

    /**
     * 设置点缓冲区大小
     * @param {Number} [radius] 半径，米
     *
     */
    _.prototype.setPointBuff = function (radius) {
        let features = this.source.getFeatures()[0]
        features.forEach(item => {
            item.getGeometry().setRadius(radius);
        });
    }

    /**
     * 画线
     *
     */
    _.prototype.DrawPolyline = function (num) {

    }

    /**
     * 设置线缓冲区大小
     * @param {Number} [radius] 半径，米
     *
     */
    _.prototype.setPolylineBuff = function (radius) {

    }

    /**
     * 画面
     *
     */
    _.prototype.DrawPolygon = function (num) {

    }

    /**
     * 设置面缓冲区
     * @param {Number} [radius] 半径，米
     *
     */
    _.prototype.setPolygonBuff = function (radius) {

    }

    //清除
    _.prototype.clearBuff = function () {
        this.source && this.source.clear();
    }

    /**
     * 开始绘制
     */
    _.prototype.start = function () {
        this.draw && this.draw.setActive(true);
    }

    /**
     * t停止绘制
     */
    _.prototype.stop = function () {
        this.draw && this.draw.setActive(false);
    }

    return _;
});
define('SGWorld/Analysis/Analysis',[
    './BufferAnalysis'
], function (
    BufferAnalysis
) {
    'use strict';

    /**
     *
     * 分析模块。
     *
     * @alias Analysis
     * @constructor
     *
     */
    function Analysis(map) {
        this._map = map;
        this._bufferAnalysis = new BufferAnalysis(map);
    };

    /**
     * 这个方法用于绘制点缓冲区
     * @param {Number} [radius]缓冲半径。
     *
     */
    Analysis.prototype.DrawPointBuffer = function (radius, callback) {
        let _bufferAnalysis = new BufferAnalysis(this._map);
        return _bufferAnalysis.DrawPoint(radius, callback);
    }
    /**
     * 这个方法用于绘制线缓冲区
     * @param {Number} [radius]缓冲半径。
     *
     */
    Analysis.prototype.DrawPolylineBuffer = function (radius) {
        return this._bufferAnalysis.DrawPolyline(radius);
    }
    /**
     * 这个方法用于绘制面缓冲区
     * @param {Number} [radius]缓冲半径。
     *
     */
    Analysis.prototype.DrawPolygonBuffer = function (radius) {
        return this._bufferAnalysis.DrawPolygon(radius);
    }

    return Analysis;
});
/**
 *
 *      实现功能：框架主要入口，二维的创建、接口的初始化等。
 *
 *      创建人员：张丹钊
 *
 *      创建日期：2020-03-17
 *
 *      参与人员：张丹钊
 *
 *      最后修改人员：张丹钊
 *
 *      最后修改时间：2020-03-17
 *
 * */
define('SGWorld/SGWorld',[
    "./Navigate/Navigate",
    "./Creator/Creator",
    "./Command/Command",
    "./Analysis/Analysis",
    "./Core/Core"
], function (
    Navigate,
    Creator,
    Command,
    Analysis,
    Core
) {
    'use strict';

    /**
     *
     * 二维控制的主要接口，通过这个接口可以控制二维和获取二维信息。
     *
     * @alias SGWorld
     * @constructor
     *
     * @param {Element|String} container 包含二维的容器ID或者Dom元素。
     * @param {option}
     *
     * @example
     * //初始化SGWorld部件
     * var sgworld = new SmartEarth2D.SGWorld('Container');
     *
     */
    function SGWorld(container, option, func) {
        this._core = new Core();
        this._core.addEPSG('EPSG:4490');

        var defaultOption = {
            target: container,
            layers: [
                new ol.layer.Tile({
                    className: '默认天地图影像',
                    source: new ol.source.XYZ({
                        url: 'http://t4.tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=837264f46e683ec982d452e78d71052e'
                    })
                })
            ],
            view: new ol.View({
                center: ol.proj.fromLonLat([110, 32]),
                zoom: 4
            })
        };

        if (option && option.center) {
            !option.projection && (option.projection = 'EPSG:4326');
            if (option.projection === 'EPSG:4490') this._core.addEPSG('EPSG:4490');
            let projection = ol.proj.get(option.projection);

            defaultOption.view = new ol.View({
                center: option.center,
                zoom: option.zoom !== undefined ? option.zoom : 2,
                projection: projection
            })
        }
        !option && (option = {});

        defaultOption = this._core.extend(defaultOption, option, true);

        this.map = new ol.Map(defaultOption);
        return this;
    }

    Object.defineProperties(SGWorld.prototype, {
        /**
         * Gets the Analysis.
         * @memberof SGWorld.prototype
         * @type {Analysis}
         * @readonly
         */
        Analysis: {
            get: function () {
                if (this._Analysis == undefined) {
                    this._Analysis = new Analysis(this.map);
                }
                return this._Analysis;
            }
        },
        /**
         * Gets the Navigate.
         * @memberof SGWorld.prototype
         * @type {Navigate}
         * @readonly
         */
        Navigate: {
            get: function () {

                if (this._Navigate == undefined) {
                    this._Navigate = new Navigate();
                }
                return this._Navigate;
            }
        },
        /**
         * Gets the Creator.
         * @memberof SGWorld.prototype
         * @type {Creator}
         * @readonly
         */
        Creator: {
            get: function () {
                if (this._Creator == undefined) {
                    this._Creator = new Creator(this.map);
                }
                return this._Creator;
            }
        },
        /**
         * Gets the Core.
         * @memberof SGWorld.prototype
         * @type {Core}
         * @readonly
         */
        Core: {
            get: function () {
                if (this._Core == undefined) {
                    this._Core = new Core();
                }
                return this._Core;
            }
        },
        /**
         * Gets the Command.
         * @memberof SGWorld.prototype
         * @type {Command}
         * @readonly
         */
        Command: {
            get: function () {
                if (this._Command == undefined) {
                    this._Command = new Command();
                }
                return this._Command;
            }
        },
        /**
         * Gets the Layers.
         * @memberof SGWorld.prototype
         * @type {Command}
         * @readonly
         */
        Layers: {
            get: function () {
                if (this.map === undefined) {
                    return null;
                }
                return this.map.getLayers();
            }
        },
        /**
         * Gets the View.
         * @memberof SGWorld.prototype
         * @type {Command}
         * @readonly
         */
        View: {
            get: function () {
                if (this.map === undefined) {
                    return null;
                }
                return this.map.getView();
            }
        }

    });

    return SGWorld;
});
define('SGWorld/Core/defined',[],function() {
    'use strict';

    /**
     * @exports defined
     *
     * @param {*} value The object.
     * @returns {Boolean} Returns true if the object is defined, returns false otherwise.
     *
     * @example
     * if (SmatrEarth2D.defined(positions)) {
     *      doSomething();
     * } else {
     *      doSomethingElse();
     * }
     */
    function defined(value) {
        return value !== undefined && value !== null;
    }

    return defined;
});

define('SGWorld/Core/defineProperties',[
        './defined'
    ], function(
        defined) {
    'use strict';

    var definePropertyWorks = (function() {
        try {
            return 'x' in Object.defineProperty({}, 'x', {});
        } catch (e) {
            return false;
        }
    })();

    /**
     * Defines properties on an object, using Object.defineProperties if available,
     * otherwise returns the object unchanged.  This function should be used in
     * setup code to prevent errors from completely halting JavaScript execution
     * in legacy browsers.
     *
     * @private
     *
     * @exports defineProperties
     */
    var defineProperties = Object.defineProperties;
    if (!definePropertyWorks || !defined(defineProperties)) {
        defineProperties = function(o) {
            return o;
        };
    }

    return defineProperties;
});

define('SGWorld/Core/jquery',[], function () {
    return $
});
/**
 *
 *      实现功能：同步加载js文件。
 *
 *      创建人员：张丹钊
 *
 *      创建日期：2020-03-17
 *
 *      参与人员：张丹钊
 *
 *      最后修改人员：张丹钊
 *
 *      最后修改时间：2020-03-17
 *
 * */
define('SGWorld/Core/Skip',[], function () {
    'use strict';

    function _(type) {
        this.async = (type === undefined ? true : type);
    }

    //获取XMLHttpRequest对象(提供客户端同http服务器通讯的协议)
    _.prototype.getXmlHttpRequest = function () {
        if (window.XMLHttpRequest) // 除了IE外的其它浏览器
            return new XMLHttpRequest();
        else if (window.ActiveXObject) // IE
            return new ActiveXObject("MsXml2.XmlHttp");
    };
    //导入内容
    _.prototype.includeJsText = function (rootObject, jsText) {
        if (rootObject != null) {
            var oScript = document.createElement("script");
            oScript.type = "text/javascript";
            oScript.text = jsText;
            rootObject.appendChild(oScript);
        }
    };
    //导入文件
    _.prototype.includeJsSrc = function (rootObject, fileUrl) {
        if (rootObject != null) {
            var oScript = document.createElement("script");
            oScript.type = "text/javascript";
            oScript.src = fileUrl;
            rootObject.appendChild(oScript);
        }
    };
    //同步加载
    _.prototype.addJs = function (rootObject, url) {
        var oXmlHttp = this.getXmlHttpRequest();
        var _this = this;
        oXmlHttp.onreadystatechange = function () {
            if (oXmlHttp.readyState === 4) {  //当执行完成以后(返回了响应)所要执行的
                if (oXmlHttp.status === 200 || oXmlHttp.status === 304) { //200有读取对应的url文件,404表示不存在这个文件
                    _this.includeJsSrc(rootObject, url);
                } else {
                    alert('XML request error: ' + oXmlHttp.statusText + ' (' + oXmlHttp.status + ')');
                }
            }
        };
        oXmlHttp.open('GET', url, _this.async); //url为js文件时,ie会自动生成 '<script src="*.js" type="text/javascript"> </scr ipt>',ff不会
        oXmlHttp.send(null);
        _this.includeJsText(rootObject, oXmlHttp.responseText);
    };
    return _;
});
define('SmartEarth2D',['./SGWorld/SGWorld', 
	'./SGWorld/Analysis/Analysis', 
	'./SGWorld/Analysis/BufferAnalysis', 
	'./SGWorld/Command/Command', 
	'./SGWorld/Command/execute', 
	'./SGWorld/Core/Core', 
	'./SGWorld/Core/defined', 
	'./SGWorld/Core/defineProperties', 
	'./SGWorld/Core/jquery', 
	'./SGWorld/Core/Skip', 
	'./SGWorld/Creator/Circle', 
	'./SGWorld/Creator/Color', 
	'./SGWorld/Creator/Creator', 
	'./SGWorld/Creator/Layer', 
	'./SGWorld/Creator/Measure', 
	'./SGWorld/Creator/MilitaryObject', 
	'./SGWorld/Creator/Point', 
	'./SGWorld/Creator/Polygon', 
	'./SGWorld/Creator/Polyline', 
	'./SGWorld/Creator/Rectangle', 
	'./SGWorld/Creator/Star', 
	'./SGWorld/Creator/WfsFeatureLayer', 
	'./SGWorld/Creator/WmsFeatureLayer', 
	'./SGWorld/Creator/WmtsFeatureLayer', 
	'./SGWorld/Navigate/flyTo', 
	'./SGWorld/Navigate/Navigate'], 
	function (SGWorld_SGWorld, 
		SGWorld_Analysis_Analysis, 
		SGWorld_Analysis_BufferAnalysis, 
		SGWorld_Command_Command, 
		SGWorld_Command_execute, 
		SGWorld_Core_Core, 
		SGWorld_Core_defined, 
		SGWorld_Core_defineProperties, 
		SGWorld_Core_jquery, 
		SGWorld_Core_Skip, 
		SGWorld_Creator_Circle, 
		SGWorld_Creator_Color, 
		SGWorld_Creator_Creator, 
		SGWorld_Creator_Layer, 
		SGWorld_Creator_Measure, 
		SGWorld_Creator_MilitaryObject, 
		SGWorld_Creator_Point, 
		SGWorld_Creator_Polygon, 
		SGWorld_Creator_Polyline, 
		SGWorld_Creator_Rectangle, 
		SGWorld_Creator_Star, 
		SGWorld_Creator_WfsFeatureLayer, 
		SGWorld_Creator_WmsFeatureLayer, 
		SGWorld_Creator_WmtsFeatureLayer, 
		SGWorld_Navigate_flyTo, 
		SGWorld_Navigate_Navigate) {
    	'use strict';
    	var SmartEarth2D = {
    		VERSION: '1.0'
    	};
    	SmartEarth2D['SGWorld'] = SGWorld_SGWorld;
		SmartEarth2D['Analysis'] = SGWorld_Analysis_Analysis;
		SmartEarth2D['BufferAnalysis'] = SGWorld_Analysis_BufferAnalysis;
		SmartEarth2D['Command'] = SGWorld_Command_Command;
		SmartEarth2D['execute'] = SGWorld_Command_execute;
		SmartEarth2D['Core'] = SGWorld_Core_Core;
		SmartEarth2D['defined'] = SGWorld_Core_defined;
		SmartEarth2D['defineProperties'] = SGWorld_Core_defineProperties;
		SmartEarth2D['jquery'] = SGWorld_Core_jquery;
		SmartEarth2D['Skip'] = SGWorld_Core_Skip;
		SmartEarth2D['Circle'] = SGWorld_Creator_Circle;
		SmartEarth2D['Color'] = SGWorld_Creator_Color;
		SmartEarth2D['Creator'] = SGWorld_Creator_Creator;
		SmartEarth2D['Layer'] = SGWorld_Creator_Layer;
		SmartEarth2D['Measure'] = SGWorld_Creator_Measure;
		SmartEarth2D['MilitaryObject'] = SGWorld_Creator_MilitaryObject;
		SmartEarth2D['Point'] = SGWorld_Creator_Point;
		SmartEarth2D['Polygon'] = SGWorld_Creator_Polygon;
		SmartEarth2D['Polyline'] = SGWorld_Creator_Polyline;
		SmartEarth2D['Rectangle'] = SGWorld_Creator_Rectangle;
		SmartEarth2D['Star'] = SGWorld_Creator_Star;
		SmartEarth2D['WfsFeatureLayer'] = SGWorld_Creator_WfsFeatureLayer;
		SmartEarth2D['WmsFeatureLayer'] = SGWorld_Creator_WmsFeatureLayer;
		SmartEarth2D['WmtsFeatureLayer'] = SGWorld_Creator_WmtsFeatureLayer;
		SmartEarth2D['flyTo'] = SGWorld_Navigate_flyTo;
		SmartEarth2D['Navigate'] = SGWorld_Navigate_Navigate;
    	return SmartEarth2D;
	});

/*global require*/
// require in the complete SmartEarth object and reassign it globally.
// This is meant for use with the Almond loader.
require([
    './SmartEarth2D',
    './SGWorld/Core/Skip'
], function (
    SmartEarth2D,
    Skip
) {
    'use strict';
    /*global self*/
    var scope = typeof window !== 'undefined' ? window : typeof self !== 'undefined' ? self : {};

    scope.SmartEarth2D = SmartEarth2D;

    var currentScript = document.currentScript;
    var endIndex = currentScript.src.indexOf('SmartEarth2D.js');
    if (endIndex < 0) {
        endIndex = currentScript.src.indexOf('SmartEarth2D.min.js');
    }
    var rootUrl = currentScript.src.substring(0, endIndex);
    var links = document.getElementsByTagName('link');
    var HaveCSS = false;
    for (var i = 0; i < links.length; i++) {
        if (links[i].href.indexOf('ol/ol.css') !== -1) {
            HaveCSS = true;
            break;
        }
    }
    if (!HaveCSS) {
        var link = document.createElement("link");
        link.rel = "stylesheet";
        link.type = "text/css";
        link.href = rootUrl + 'ol/ol.css';
        document.head.appendChild(link);
    }

    var SkipTool = new Skip(false);

    SkipTool.addJs(document.body, rootUrl + 'ol/ol.js');
    scope.SmartEarth2D.ol = scope.ol = ol;

    SkipTool.addJs(document.body, rootUrl + 'proj4/dist/proj4.js');
    scope.SmartEarth2D.proj4 = scope.proj4 = proj4;

}, undefined, true);


}());